URL может содержать только ограниченный набор символов (буквы, цифры, -, _, ., ~ и несколько других). Остальные символы — пробелы, кириллица, спецсимволы — должны быть закодированы в виде %XX, где XX — шестнадцатеричный код символа. В этой статье разберём, когда и как применять кодирование, чем отличаются encodeURIComponent и encodeURI, и типичные ошибки.
Для кодирования и декодирования URL используйте URL Encoder на reChecker.
Зачем кодировать URL
Пробелы и спецсимволы
Пробел в URL недопустим. Он кодируется как %20 или + (в application/x-www-form-urlencoded). Символы вроде &, =, ?, # имеют специальное значение — их кодирование предотвращает некорректный разбор URL.
Кириллица и Unicode
URL исторически основан на ASCII. Символы вне ASCII (кириллица, иероглифы, диакритики) кодируются в UTF-8, а каждый байт — в %XX:
"Привет" → %D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82
Современные браузеры отображают Unicode в адресной строке, но при отправке запросов используют percent-encoded форму.
Резервные символы
Символы !$&'()*+,;=:@ в некоторых контекстах допустимы без кодирования (RFC 3986), но для надёжности их часто кодируют при использовании в query-параметрах.
encodeURIComponent vs encodeURI
В JavaScript есть две функции. Разница — в наборе кодируемых символов.
encodeURIComponent
Кодирует почти всё, кроме A-Z a-z 0-9 - _ . ! ~ * ' ( ). Предназначена для значений параметров, а не для целого URL.
encodeURIComponent('a & b = c');
// "a%20%26%20b%20%3D%20c"
encodeURIComponent('Привет');
// "%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82"
Используйте для каждого параметра отдельно:
const query = 'поиск';
const url = `https://example.com/search?q=${encodeURIComponent(query)}`;
// https://example.com/search?q=%D0%BF%D0%BE%D0%B8%D1%81%D0%BA
encodeURI
Кодирует только символы, недопустимые в URL, но не трогает ; , / ? : @ & = + $ #. Предназначена для целого URL, а не для частей.
encodeURI('https://example.com/path?name=Иван');
// "https://example.com/path?name=%D0%98%D0%B2%D0%B0%D0%BD"
Если применить encodeURIComponent к целому URL, сломаются слэши и протокол:
encodeURIComponent('https://example.com/path');
// "https%3A%2F%2Fexample.com%2Fpath" — невалидный URL
Сравнение
| Функция | Кодирует | Применение |
|---|---|---|
| encodeURIComponent | Всё кроме букв, цифр, -_.!~*'() | Значения query-параметров, fragment |
| encodeURI | Только недопустимые в URL | Целый URL (path + query уже сформированы) |
Декодирование
decodeURIComponent('%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82');
// "Привет"
decodeURI('https://example.com/path?name=%D0%98%D0%B2%D0%B0%D0%BD');
// "https://example.com/path?name=Иван"
Используйте decodeURIComponent для значений параметров. decodeURI — для целого URL.
application/x-www-form-urlencoded
При отправке форм с Content-Type: application/x-www-form-urlencoded пробелы кодируются как +, а не %20. При парсинге на сервере + декодируется в пробел. В encodeURIComponent пробел даёт %20. Для совместимости с формами можно заменить:
function encodeFormValue(str) {
return encodeURIComponent(str).replace(/%20/g, '+');
}
В большинстве современных API и fetch с URLSearchParams используется %20, и серверы корректно обрабатывают оба варианта.
Типичные ошибки
Кодирование целого URL
// Неправильно
const url = encodeURIComponent('https://example.com/search?q=test');
// Правильно
const base = 'https://example.com/search';
const url = `${base}?q=${encodeURIComponent('test')}`;
Двойное кодирование
Если значение уже закодировано, повторное кодирование приведёт к некорректному результату:
encodeURIComponent('%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82');
// "%25D0%259F%25D1%2580%25D0%25B8%25D0%25B2%25D0%25B5%25D1%2582" — двойное кодирование
Проверяйте источник данных. При получении из другого API значение может быть уже закодировано.
Кодирование имени параметра
Имена параметров тоже должны быть закодированы, если содержат спецсимволы:
const params = { 'user name': 'Иван' };
const query = Object.entries(params)
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join('&');
// user%20name=%D0%98%D0%B2%D0%B0%D0%BD
URLSearchParams
Современный API для работы с query-строками автоматически кодирует значения:
const params = new URLSearchParams();
params.set('q', 'поиск');
params.set('page', '1');
params.toString();
// "q=%D0%BF%D0%BE%D0%B8%D1%81%D0%BA&page=1"
Рекомендуется использовать URLSearchParams вместо ручной конкатенации — меньше шансов ошибиться.
Практические рекомендации
- Query-параметры — всегда кодируйте значения через
encodeURIComponentилиURLSearchParams - Path-сегменты — если сегмент содержит спецсимволы или кириллицу, кодируйте каждый сегмент отдельно
- Проверка — используйте URL Encoder на reChecker для проверки корректности кодирования
- Сервер — убедитесь, что бэкенд корректно декодирует параметры (многие фреймворки делают это автоматически)
- Редиректы — при формировании URL для 302/301 кодируйте все динамические части
Правильное кодирование URL предотвращает ошибки при передаче кириллицы, пробелов и спецсимволов. Инструмент URL Encoder помогает быстро проверить и сгенерировать корректные строки.
Специальные символы в path
В path-сегментах допустимы буквы, цифры и ограниченный набор символов: -, ., _, ~. Слэш / разделяет сегменты и не кодируется внутри path. При формировании динамических путей (например, из названия файла) кодируйте каждый сегмент:
const filename = 'документ (1).pdf';
const path = `/files/${encodeURIComponent(filename)}`;
Кодирование в разных языках
- PHP:
rawurlencode()для path и значений параметров (пробел →%20),urlencode()для form data (пробел →+) - Python:
urllib.parse.quote()сsafeдля указания не кодируемых символов - Java:
URLEncoder.encode()— для form data; для path используйтеURIилиURLс корректным разбором
Проверка результата через URL Encoder на reChecker помогает убедиться в корректности при работе с разными стеками.
Punycode для международных доменов
Домены с кириллицей (например, сайт.рф) кодируются в Punycode (xn--80aswg.xn--p1ai). Браузеры отображают Unicode, но при разрешении DNS и в заголовках используется Punycode. Для кодирования/декодирования Punycode в JavaScript применяют url.domainToASCII() и url.domainToUnicode().
Кодирование в fetch и XMLHttpRequest
При передаче параметров в fetch используйте URLSearchParams или вручную кодируйте значения:
const params = { q: 'поиск', page: 1 };
const query = new URLSearchParams(params).toString();
fetch(`/api/search?${query}`);
Для POST с application/x-www-form-urlencoded тело запроса тоже должно быть закодировано. URLSearchParams при передаче в body делает это автоматически.
Обработка на сервере
Серверы и фреймворки обычно декодируют параметры автоматически. Проверьте настройки: некоторые прокси или CDN могут изменять кодировку. При ручном парсинге query-строки используйте встроенные парсеры (URL, URLSearchParams) — они корректно обрабатывают edge cases.