L'encodage URL (egalement connu sous le nom d'encodage pourcent) est l'un des mecanismes les plus essentiels du developpement web. Chaque fois que vous soumettez un formulaire, cliquez sur un lien avec des parametres de requete ou appelez une API REST, des operations d'encodage et de decodage URL se produisent. Ce guide complet couvre tout, de la specification RFC 3986 aux exemples de code pratiques en JavaScript, Python, Bash, PHP et Java.
Essayez notre outil gratuit d'encodage/decodage URL en ligne.
Qu'est-ce que l'encodage URL (encodage pourcent) ?
L'encodage URL, defini dans la RFC 3986, remplace les caracteres non securises par un signe pourcent (%) suivi de deux chiffres hexadecimaux. Par exemple, un espace devient %20.
Les URLs ne peuvent contenir qu'un ensemble limite de caracteres ASCII. Les caracteres surs qui n'ont pas besoin d'encodage sont : lettres, chiffres et quatre caracteres speciaux : -, _, ., ~. Tous les autres caracteres doivent etre encodes.
Les caracteres comme &, =, ? et # ont des significations structurelles dans les URLs. Sans encodage URL, les URLs seraient cassees ou mal interpretees.
Comment fonctionne l'encodage URL
Le processus d'encodage URL suit un algorithme simple :
- Convertir le caractere en octets UTF-8.
- Pour chaque octet, ecrire
%suivi de la valeur hexadecimale. - Les caracteres non reserves restent inchanges.
- Les caracteres reserves ne sont encodes que dans les contextes ou ils seraient mal interpretes.
Exemple : Hello World! devient Hello%20World%21.
Exemple multi-octets UTF-8 : Les caracteres non-ASCII produisent plusieurs octets percent-encodes.
Table de reference d'encodage URL
Table de reference des caracteres couramment encodes :
| Character | Encoded | Description |
|---|---|---|
(space) | %20 | Space |
! | %21 | Exclamation mark |
# | %23 | Hash / Fragment |
$ | %24 | Dollar sign |
% | %25 | Percent sign |
& | %26 | Ampersand |
' | %27 | Apostrophe |
( | %28 | Left parenthesis |
) | %29 | Right parenthesis |
* | %2A | Asterisk |
+ | %2B | Plus sign |
, | %2C | Comma |
/ | %2F | Forward slash |
: | %3A | Colon |
; | %3B | Semicolon |
= | %3D | Equals sign |
? | %3F | Question mark |
@ | %40 | At sign |
[ | %5B | Left bracket |
] | %5D | Right bracket |
{ | %7B | Left brace |
} | %7D | Right brace |
| | %7C | Pipe |
< | %3C | Less than |
> | %3E | Greater than |
" | %22 | Double quote |
Encodage des espaces : %20 vs +
Il existe deux facons d'encoder les espaces dans les URLs :
%20 : Encodage standard RFC 3986 pour les URIs.
+ : Utilise par application/x-www-form-urlencoded (formulaires HTML).
Lequel utiliser ? Utilisez %20 pour construire des URLs programmatiquement. Le + est utilise automatiquement pour les formulaires.
// Space encoding comparison
// RFC 3986 (URI standard) — space = %20
"hello world" → "hello%20world"
// Used in: URL paths, API endpoints, general URIs
// application/x-www-form-urlencoded — space = +
"hello world" → "hello+world"
// Used in: HTML form submissions, URLSearchParams
// JavaScript comparison:
encodeURIComponent("hello world") // "hello%20world" (%20)
new URLSearchParams({q: "hello world"}).toString() // "q=hello+world" (+)
// Python comparison:
urllib.parse.quote("hello world") # "hello%20world" (%20)
urllib.parse.urlencode({"q": "hello world"}) # "q=hello+world" (+)
// PHP comparison:
rawurlencode("hello world") // "hello%20world" (%20)
urlencode("hello world") // "hello+world" (+)Exemples de code d'encodage/decodage URL
JavaScript encodage/decodage URL
JavaScript offre encodeURIComponent et encodeURI. Comprendre quand utiliser chacun est essentiel :
// ===== encodeURIComponent vs encodeURI =====
// encodeURIComponent — encodes EVERYTHING except: A-Z a-z 0-9 - _ . ~
// Use for: individual query parameter values, path segments
encodeURIComponent("hello world & goodbye");
// "hello%20world%20%26%20goodbye"
encodeURIComponent("price=100&category=books");
// "price%3D100%26category%3Dbooks"
// encodeURI — preserves URL structure characters: : / ? # & = @ + $
// Use for: encoding a complete URL
encodeURI("https://example.com/search?q=hello world&lang=en");
// "https://example.com/search?q=hello%20world&lang=en"
// WARNING: Do NOT use encodeURIComponent on full URLs!
encodeURIComponent("https://example.com/path");
// "https%3A%2F%2Fexample.com%2Fpath" ← BROKEN URL!
// ===== Decoding =====
decodeURIComponent("hello%20world%20%26%20goodbye");
// "hello world & goodbye"
decodeURI("https://example.com/search?q=hello%20world");
// "https://example.com/search?q=hello world"
// ===== URLSearchParams (handles form encoding automatically) =====
const params = new URLSearchParams({
query: "cats & dogs",
page: "1",
filter: "price > 50"
});
params.toString();
// "query=cats+%26+dogs&page=1&filter=price+%3E+50"
// Note: spaces become + (form encoding), & in values becomes %26
// Parse query string
const parsed = new URLSearchParams("?q=hello+world&lang=en");
parsed.get("q"); // "hello world" (+ decoded to space)
parsed.get("lang"); // "en"
// ===== Building URLs with the URL API =====
const url = new URL("https://api.example.com/search");
url.searchParams.set("q", "hello world & more");
url.searchParams.set("limit", "10");
url.toString();
// "https://api.example.com/search?q=hello+world+%26+more&limit=10"Python encodage/decodage URL
Le module urllib.parse de Python fournit des fonctions completes d'encodage URL :
import urllib.parse
# ===== quote / unquote (RFC 3986 percent-encoding) =====
# Encode a string (spaces become %20)
urllib.parse.quote("hello world & goodbye")
# "hello%20world%20%26%20goodbye"
# By default, / is NOT encoded (safe="/")
urllib.parse.quote("/path/to/file name.txt")
# "/path/to/file%20name.txt"
# Encode everything including /
urllib.parse.quote("/path/to/file", safe="")
# "%2Fpath%2Fto%2Ffile"
# Decode
urllib.parse.unquote("hello%20world%20%26%20goodbye")
# "hello world & goodbye"
# ===== urlencode (for query strings, uses + for spaces) =====
params = {"q": "cats & dogs", "page": 1, "filter": "price > 50"}
urllib.parse.urlencode(params)
# "q=cats+%26+dogs&page=1&filter=price+%3E+50"
# ===== quote_plus (form encoding, spaces become +) =====
urllib.parse.quote_plus("hello world")
# "hello+world"
urllib.parse.unquote_plus("hello+world")
# "hello world"
# ===== With the requests library =====
import requests
# requests handles URL encoding automatically
response = requests.get(
"https://api.example.com/search",
params={"q": "hello world", "lang": "en"}
)
# Actual URL: https://api.example.com/search?q=hello+world&lang=en
# For path segments, encode manually
username = "john@example.com"
url = f"https://api.example.com/users/{urllib.parse.quote(username, safe='')}"
# "https://api.example.com/users/john%40example.com"Bash / curl encodage URL
Avec curl, le flag --data-urlencode est l'approche la plus simple :
# ===== curl --data-urlencode =====
# GET request with URL-encoded query parameter
curl -G "https://api.example.com/search" \
--data-urlencode "q=hello world & more" \
--data-urlencode "lang=en"
# Request URL: /search?q=hello%20world%20%26%20more&lang=en
# POST with form-encoded body
curl -X POST "https://api.example.com/submit" \
--data-urlencode "name=John Doe" \
--data-urlencode "message=Hello! How are you?"
# ===== Pure Bash URL encoding (using printf) =====
urlencode() {
local string="${1}"
local strlen=${#string}
local encoded=""
local pos c o
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9]) o="${c}" ;;
*) printf -v o '%%%02X' "'$c" ;;
esac
encoded+="${o}"
done
echo "${encoded}"
}
urlencode "hello world & goodbye"
# "hello%20world%20%26%20goodbye"
# ===== Using Python one-liner in Bash =====
python3 -c "import urllib.parse; print(urllib.parse.quote('hello world'))"
# "hello%20world"
# ===== Decode URL-encoded strings =====
python3 -c "import urllib.parse; print(urllib.parse.unquote('hello%20world'))"
# "hello world"PHP encodage/decodage URL
PHP fournit urlencode() et rawurlencode() :
<?php
// ===== urlencode / urldecode =====
// Uses + for spaces (application/x-www-form-urlencoded)
echo urlencode("hello world & goodbye");
// "hello+world+%26+goodbye"
echo urldecode("hello+world+%26+goodbye");
// "hello world & goodbye"
// ===== rawurlencode / rawurldecode =====
// Uses %20 for spaces (RFC 3986)
echo rawurlencode("hello world & goodbye");
// "hello%20world%20%26%20goodbye"
echo rawurldecode("hello%20world%20%26%20goodbye");
// "hello world & goodbye"
// ===== When to use which? =====
// urlencode() → for query string values (form-style)
// rawurlencode() → for URL path segments (RFC 3986)
// Building a URL with encoded path and query
$path = rawurlencode("my file.pdf");
$query = urlencode("search term & more");
$url = "https://example.com/files/{$path}?q={$query}";
// "https://example.com/files/my%20file.pdf?q=search+term+%26+more"
// ===== http_build_query (encode arrays as query strings) =====
$params = [
"q" => "cats & dogs",
"page" => 1,
"tags" => ["php", "url encoding"]
];
echo http_build_query($params);
// "q=cats+%26+dogs&page=1&tags%5B0%5D=php&tags%5B1%5D=url+encoding"
?>Java encodage/decodage URL
Les classes URLEncoder et URLDecoder de Java gerent l'encodage URL :
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
// ===== URLEncoder.encode (uses + for spaces) =====
// Always specify UTF-8 charset!
String encoded = URLEncoder.encode(
"hello world & goodbye", StandardCharsets.UTF_8
);
// "hello+world+%26+goodbye"
// Decode
String decoded = URLDecoder.decode(
"hello+world+%26+goodbye", StandardCharsets.UTF_8
);
// "hello world & goodbye"
// ===== Convert + to %20 for RFC 3986 compliance =====
String rfc3986 = URLEncoder.encode("hello world", StandardCharsets.UTF_8)
.replace("+", "%20");
// "hello%20world"
// ===== Java 11+ URI encoding =====
import java.net.URI;
URI uri = URI.create("https://example.com/search");
// For building URLs with encoded parameters:
String query = "q=" + URLEncoder.encode("hello world", StandardCharsets.UTF_8);
URI fullUri = URI.create("https://example.com/search?" + query);
// https://example.com/search?q=hello+world
// ===== Encoding path segments =====
String pathSegment = URLEncoder.encode("my file.pdf", StandardCharsets.UTF_8)
.replace("+", "%20");
String url = "https://example.com/files/" + pathSegment;
// "https://example.com/files/my%20file.pdf"Erreurs courantes d'encodage URL
Les pieges les plus courants a eviter :
Double encodage : Encoder une chaine deja encodee. %20 devient %2520.
// Double encoding example — a common bug!
const value = "hello world";
// Correct: encode once
const correct = encodeURIComponent(value);
// "hello%20world" ✓
// Bug: encode twice
const doubleEncoded = encodeURIComponent(encodeURIComponent(value));
// "hello%2520world" ✗ (%25 is the encoded form of %)
// How to detect double encoding:
// If you see %25 in your URLs, you likely have a double encoding issue
// %2520 = double-encoded space (%25 = %, 20 = space)
// %253A = double-encoded colon (%25 = %, 3A = :)Encoder l'URL entiere : Utiliser encodeURIComponent() sur une URL complete casse la structure.
// Encoding the entire URL — WRONG!
const url = "https://example.com/path?q=hello world";
// WRONG: breaks URL structure
encodeURIComponent(url);
// "https%3A%2F%2Fexample.com%2Fpath%3Fq%3Dhello%20world"
// CORRECT option 1: use encodeURI for full URLs
encodeURI(url);
// "https://example.com/path?q=hello%20world"
// CORRECT option 2: encode only the value
const base = "https://example.com/path";
const query = encodeURIComponent("hello world");
const fullUrl = base + "?q=" + query;
// "https://example.com/path?q=hello%20world"Oublier UTF-8 : Toujours utiliser UTF-8 pour l'encodage URL.
Ne pas encoder les segments de chemin : Les chemins avec espaces doivent aussi etre encodes.
Mauvaise gestion du signe + : + signifie espace dans les formulaires, mais c'est un literal dans les URLs.
Encodage URL dans les APIs
Comprendre l'encodage URL est crucial pour les APIs :
Parametres de requete : Chaque nom et valeur de parametre doit etre encode individuellement.
Parametres de chemin : Les valeurs dans les chemins d'URL doivent aussi etre encodees.
Donnees de formulaire : application/x-www-form-urlencoded utilise + pour les espaces.
Charges JSON : Le contenu JSON dans le corps d'une requete n'a pas besoin d'encodage URL.
// API URL encoding examples
// Query parameters — encode each value individually
const searchTerm = 'price > 100 & category = "electronics"';
const apiUrl = `https://api.example.com/search?q=${encodeURIComponent(searchTerm)}&limit=10`;
// "https://api.example.com/search?q=price%20%3E%20100%20%26%20...&limit=10"
// Path parameters — encode values embedded in paths
const username = "john@example.com";
const profileUrl = `https://api.example.com/users/${encodeURIComponent(username)}/profile`;
// "https://api.example.com/users/john%40example.com/profile"
// Form data (POST) — uses + for spaces
const formBody = new URLSearchParams({
username: "john doe",
password: "p@ss w0rd!"
}).toString();
// "username=john+doe&password=p%40ss+w0rd%21"
// JSON as query parameter — encode the entire JSON string
const filters = JSON.stringify({ price: { min: 10, max: 100 } });
const url = `/api/products?filters=${encodeURIComponent(filters)}`;
// "/api/products?filters=%7B%22price%22%3A%7B%22min%22%3A10%2C%22max%22%3A100%7D%7D"Questions frequemment posees
Qu'est-ce que l'encodage URL et pourquoi est-il necessaire ?
L'encodage URL remplace les caracteres non securises par des sequences pourcent-hexadecimales pour une transmission sure dans les URLs. Les caracteres speciaux comme &, =, ? et # ont des significations structurelles et doivent etre encodes comme donnees.
Quelle est la difference entre encodeURI et encodeURIComponent ?
encodeURI() preserve les caracteres structurels de l'URL (:, /, ?, #). encodeURIComponent() encode tout sauf les caracteres non reserves. Utilisez encodeURIComponent pour les valeurs de parametres individuels.
Faut-il utiliser %20 ou + pour les espaces ?
Utilisez %20 pour les URLs (RFC 3986). Utilisez + uniquement pour application/x-www-form-urlencoded. En cas de doute, %20 est le choix le plus sur.
L'encodage URL est une competence fondamentale du developpement web. Utilisez notre outil gratuit pour un encodage et decodage instantanes.
Encodez et decodez des URLs instantanement avec notre outil gratuit.