Кодирование и декодирование URL
URL encode и decode: кириллица, пробелы и спецсимволы в адресе, разбор параметров, windows-1251.
Данные обрабатываются в браузере и никуда не отправляются
Как пользоваться
Выберите режим, вставьте текст слева - результат появляется сразу, без кнопок. В режиме «Кодировать» текст превращается в безопасную для адреса строку с %-последовательностями, в режиме «Декодировать» - наоборот. Если нужна обратная операция, нажмите «Поменять местами»: результат станет входными данными, а режим переключится. В режиме декодирования адрес дополнительно разбирается на части: протокол, хост, путь и таблица параметров запроса - уже раскодированные.
Способ кодирования определяет, какие символы остаются как есть. Для значения параметра или сегмента пути берите «Компонент»: он закодирует все служебные знаки (/ ? & = # и другие). «Адрес целиком» подходит только для готового адреса, у которого нужно экранировать пробелы и кириллицу, не ломая https://, ? и &. «Строгий RFC 3986» кодирует ещё и ! * ' ( ) - это поведение rawurlencode в PHP. «Форма» кодирует пробел знаком «+», как это делают HTML-формы и urlencode в PHP. Кодировка по умолчанию - UTF-8, это стандарт; windows-1251 и KOI8-R нужны только для старых сайтов.
Справочник символов
| Символ | Код | Роль в адресе |
|---|---|---|
| пробел | %20 | В данных формы заменяется на «+» |
| ! | %21 | Служебный символ (sub-delim), в encodeURIComponent не кодируется |
| " | %22 | Ограничитель значений в HTML |
| # | %23 | Начало якоря (fragment), на сервер не передаётся |
| $ | %24 | Служебный символ (sub-delim) |
| % | %25 | Признак закодированного символа, сам кодируется как %25 |
| & | %26 | Разделитель параметров запроса |
| ' | %27 | Служебный символ (sub-delim), в encodeURIComponent не кодируется |
| ( ) | %28 %29 | Служебные символы (sub-delim) |
| * | %2A | Служебный символ (sub-delim) |
| + | %2B | В данных формы означает пробел, в пути - обычный плюс |
| , | %2C | Разделитель значений |
| / | %2F | Разделитель сегментов пути |
| : | %3A | Отделяет протокол, порт и пароль |
| ; | %3B | Разделитель параметров |
| < > | %3C %3E | Угловые скобки HTML, всегда кодируются |
| = | %3D | Отделяет имя параметра от значения |
| ? | %3F | Начало строки запроса |
| @ | %40 | Отделяет пользователя от хоста |
| [ ] | %5B %5D | Адреса IPv6 в хосте |
| \ ^ ` | %5C %5E %60 | Небезопасные символы, всегда кодируются |
| { | } | %7B %7C %7D | Небезопасные символы, всегда кодируются |
| ~ | %7E | Не кодируется по RFC 3986 (старый urlencode в PHP кодировал) |
| я | %D1%8F | Любая не-ASCII буква: два байта UTF-8, две последовательности |
Способы кодирования
| Режим на сайте | Не кодируются | Пробел | Аналоги в языках |
|---|---|---|---|
| Компонент | A-Z a-z 0-9 - _ . ! ~ * ' ( ) | %20 | JavaScript: encodeURIComponent; C#: Uri.EscapeDataString (почти) |
| Адрес целиком | как «Компонент» плюс ; , / ? : @ & = + $ # | %20 | JavaScript: encodeURI |
| Строгий RFC 3986 | A-Z a-z 0-9 - _ . ~ | %20 | PHP: rawurlencode; Python: urllib.parse.quote(s, safe='') |
| Форма | A-Z a-z 0-9 * - _ . | + | PHP: urlencode; Python: quote_plus; Java: URLEncoder; HTML-формы и URLSearchParams |
Как сделать то же в коде
| Язык | Кодирование | Декодирование |
|---|---|---|
| JavaScript | encodeURIComponent(s) | decodeURIComponent(s) |
| PHP | rawurlencode($s) / urlencode($s) | rawurldecode($s) / urldecode($s) |
| Python | urllib.parse.quote(s, safe='') / quote_plus(s) | urllib.parse.unquote(s) / unquote_plus(s) |
| Java | URLEncoder.encode(s, StandardCharsets.UTF_8) | URLDecoder.decode(s, StandardCharsets.UTF_8) |
| C# | Uri.EscapeDataString(s) | Uri.UnescapeDataString(s) |
| Go | url.QueryEscape(s) / url.PathEscape(s) | url.QueryUnescape(s) / url.PathUnescape(s) |
| Ruby | ERB::Util.url_encode(s) | CGI.unescape(s) |
| curl | curl --data-urlencode "q=привет" | - |
Частые ошибки
Вот что чаще всего идёт не так при работе с URL-кодированием:
Кодируют весь адрес как компонент
Если пропустить через encodeURIComponent адрес целиком, он превратится в https%3A%2F%2Fexample.com%2F..., и ссылка перестанет работать: «://», «/», «?» и «&» потеряют служебный смысл. Кодируйте по отдельности значения параметров и сегменты пути, а не готовый адрес.
Кодируют уже закодированное
Повторное кодирование превращает %20 в %2520 - знак «%» сам кодируется. Если в результате видите %25 там, где ждали пробел или букву, текст закодирован дважды: декодируйте его столько раз, сколько нужно (инструмент подскажет).
Плюс вместо пробела в пути
«+» означает пробел только в данных формы (после «?»). В пути адреса плюс - обычный символ, и пробел там обязан быть %20. Поэтому для кодирования сегментов пути выбирайте «Компонент», а не «Форма».
Плюс в данных не закодирован
Значение a+b, переданное в параметре как есть, сервер прочитает как «a b». Чтобы сохранить плюс, его нужно закодировать как %2B - все способы, кроме «Адрес целиком», так и делают.
Не закодирован амперсанд или знак равенства
Значение «Tom & Jerry» без кодирования разорвёт параметры: сервер увидит параметр «Tom » и отдельный параметр « Jerry». Все значения нужно кодировать, чтобы & и = оказались %26 и %3D.
Не та кодировка
Современные сайты ждут UTF-8: «я» - это %D1%8F. Старые (и часть российских CMS) используют windows-1251, где та же буква - %FF. Если вместо текста получаются символы «�» или «РїСЂРёРІРµС‚», переключите кодировку - инструмент сам подскажет подходящую.
Частые вопросы
Что такое URL-кодирование (процентное кодирование)?
Адрес (URL) может состоять только из ограниченного набора символов ASCII: латинских букв, цифр и нескольких знаков. Всё остальное - пробелы, кириллица, иероглифы, эмодзи, а также символы, которые в адресе имеют особый смысл, - записывается последовательностью %XX, где XX - шестнадцатеричное значение байта.
Например, пробел - %20, знак вопроса - %3F, а русская буква «я» в UTF-8 занимает два байта и превращается в %D1%8F. Способ описан в стандарте RFC 3986 и называется percent-encoding. Он нужен, чтобы любые данные можно было безопасно передать в адресной строке, не нарушив структуру адреса.
Какие символы кодируются, а какие остаются как есть?
Без кодирования всегда остаются «безопасные» символы (unreserved): латинские буквы A-Z и a-z, цифры 0-9 и знаки - _ . ~.
Зарезервированные символы (reserved) ! * ' ( ) ; : @ & = + $ , / ? # [ ] имеют в адресе служебную роль. Если они часть данных, их нужно кодировать, если служебные - оставлять. Все остальные символы - пробел, кавычки, < > \ ^ ` { | }, кириллица и любые не-ASCII знаки - кодируются всегда. Полная таблица символов с кодами приведена выше, в разделе «Справочник символов».
Чем отличаются encodeURI, encodeURIComponent, rawurlencode и urlencode?
encodeURIComponent (режим «Компонент») кодирует всё, кроме букв, цифр и - _ . ! ~ * ' ( ). Его используют для значений параметров и сегментов пути.
encodeURI (режим «Адрес целиком») дополнительно оставляет служебные символы ; , / ? : @ & = + $ #, поэтому подходит только для готового адреса, в котором нужно заменить пробелы и кириллицу.
rawurlencode в PHP (режим «Строгий RFC 3986») кодирует всё, кроме букв, цифр и - _ . ~. urlencode в PHP (режим «Форма») делает то же, но пробел заменяет на «+», как браузер при отправке формы. Точное сравнение - в таблице «Способы кодирования».
Почему пробел кодируется то как %20, то как «+»?
Исторически сложились два формата. По RFC 3986 пробел везде кодируется как %20. А формат application/x-www-form-urlencoded, в котором браузеры отправляют данные HTML-форм, заменяет пробел знаком «+».
Поэтому «+» означает пробел только в строке запроса, составленной формой (после «?»), а в пути адреса «+» - обычный плюс. Если сомневаетесь, используйте %20: его правильно понимают в обоих местах. А чтобы передать сам знак плюс, всегда кодируйте его как %2B.
Нужно ли кодировать адрес целиком?
Как правило, нет. Кодировать нужно отдельные части - значения параметров и сегменты пути - до того, как вы соберёте из них адрес. Если закодировать готовый адрес как компонент, исчезнет его структура: https://site.ru/a?b=c превратится в https%3A%2F%2Fsite.ru%2Fa%3Fb%3Dc, и это уже не ссылка.
Исключение - когда адрес целиком является значением параметра другого адреса (например, redirect=https%3A%2F%2Fsite.ru%2Fa%3Fb%3Dc): тогда кодировать его как компонент как раз нужно.
Как закодировать кириллицу в URL?
Выберите режим «Компонент» (для параметров и сегментов пути) или «Адрес целиком» (для готовой ссылки) и кодировку UTF-8. Каждая русская буква занимает в UTF-8 два байта, поэтому превращается в две последовательности: «привет» - %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82. Браузеры показывают такой адрес в читаемом виде, но отправляют на сервер закодированным.
Доменные имена с кириллицей кодируются иначе - не процентами, а по алгоритму Punycode: «пример.рф» превращается в xn--e1afmkfd.xn--p1ai. Это делает сам браузер при обращении к сайту.
Что такое двойное кодирование и как его исправить?
Это ситуация, когда уже закодированную строку закодировали ещё раз: знак «%» превратился в %25, и %D0 стал %25D0. Признак - в результате декодирования вы снова видите %-последовательности, а не буквы.
Исправить просто: декодируйте строку повторно. Инструмент сам замечает такой случай и показывает кнопку «Декодировать ещё раз». Чтобы не создавать проблему, кодируйте данные ровно один раз - в том месте, где собираете адрес.
Почему при декодировании получаются «кракозябры» и при чём здесь windows-1251?
Процентное кодирование записывает байты, а то, какие это буквы, определяет кодировка. Современные сайты используют UTF-8 (буква «п» - %D0%BF), но старые российские сайты и некоторые CMS - windows-1251 (та же буква - %EF), реже KOI8-R. Если выбрана не та кодировка, вместо текста получаются символы замены «�» или нечитаемый набор вроде «РїСЂРёРІРµС‚».
Переключите кодировку - инструмент при ошибке сам определяет, что строка больше похожа на windows-1251 или KOI8-R, и предлагает её одной кнопкой.
Как кодировать и декодировать URL в JavaScript, PHP, Python и других языках?
В JavaScript - encodeURIComponent и decodeURIComponent; в PHP - rawurlencode/rawurldecode и urlencode/urldecode; в Python - urllib.parse.quote и unquote; в Java - URLEncoder.encode и URLDecoder.decode с явным указанием UTF-8; в C# - Uri.EscapeDataString и Uri.UnescapeDataString; в Go - url.QueryEscape и url.QueryUnescape.
Полная таблица с вызовами для каждого языка приведена выше, в разделе «Как сделать то же в коде». Всегда указывайте кодировку явно: если библиотека берёт её из настроек системы, на другом сервере результат может отличаться.
Можно ли использовать URL-кодирование для защиты данных?
Нет. Процентное кодирование - это не шифрование и не защита: любой человек раскодирует строку за секунду, в том числе этим же инструментом. Оно лишь делает данные безопасными для передачи в адресе. Пароли и токены в адресной строке небезопасны сами по себе: они остаются в истории браузера, журналах серверов и заголовке Referer.
Какая максимальная длина URL?
Стандарт не ограничивает длину адреса, но на практике пределы есть: браузеры и поисковые системы стабильно работают примерно до 2000 символов, веб-серверы по умолчанию принимают строку запроса порядка 8 КБ (в nginx и Apache это настраивается). Учтите, что кодирование удлиняет адрес: каждая русская буква превращается в 6 символов (%D0%BF), поэтому длинные тексты лучше передавать в теле POST-запроса, а не в адресе.
Почему часть адреса после # не попадает на сервер?
Всё после знака # - якорь (fragment) - обрабатывается только браузером и в запросе к серверу не отправляется. Поэтому его нельзя использовать для передачи данных на сервер, а в значениях параметров символ # обязательно кодируется как %23, иначе остаток строки будет отрезан.
Отправляются ли мои данные на сервер?
Нет - 100%. Сайт целиком статический, у него нет серверной части, которая могла бы принять текст. Кодирование и декодирование выполняются прямо в вашем браузере.
Похожие инструменты
Курс «Проектирование API и интеграций»
Глубокое погружение в REST, gRPC, SOAP, проектирование баз данных и брокеры сообщений (Kafka, RabbitMQ). Делегирование рутины нейросетям (ИИ). Перестанете бояться технических собеседований и начнете говорить с разработчиками на одном языке. Курс собран так, чтобы пробить зарплатный потолок и вырасти в грейде - ученики тому подтверждение.
Перейти к курсу на Stepik