🔗
Инструменты разработчика
March 19, 20267 min readBy BrowseryTools Team

Кодирование и декодирование URL: полное руководство

Как работает процентное кодирование URL, какие символы нужно кодировать, в чём разница между encodeURIComponent и encodeURI, и когда кодирование URL важно для безопасности.

urlкодированиедекодированиепроцентное кодированиевеб

URL выглядят просто снаружи — строка текста, указывающая на ресурс. Но под капотом они подчиняются строгой грамматике, допускающей лишь определённый набор символов. Стоит попытаться передать в URL пробел, амперсанд или символ не из ASCII без кодирования — и возникают ошибки, которые бывает сложно отладить. Процентное кодирование (URL-кодирование) — это механизм, позволяющий безопасно встраивать произвольные данные в URL.

Вы можете мгновенно кодировать и декодировать URL с помощью кодировщика/декодировщика URL BrowseryTools — бесплатно, без регистрации, всё остаётся в браузере.

Почему специальные символы ломают URL

Спецификация URL (RFC 3986) резервирует определённые символы для структурных целей. Знак ? отделяет путь от строки запроса. Знак & разделяет параметры запроса друг от друга. Знак # обозначает идентификатор фрагмента. Знак / разделяет сегменты пути. Если ваши данные содержат любой из этих символов, парсер URL не сможет отличить ваши данные от структуры самого URL.

Рассмотрим поисковый запрос rock & roll. При наивном построении URL получается:

/search?q=rock & roll
          ^     ^
          |     └── похоже, здесь начинается новый параметр
          └── этот & делит q и мнимый второй параметр

Парсер читает q=rock (с пробелом в конце) как первый параметр, затем встречает то, что похоже на начало второго параметра с именем roll. Оба значения неверны. Правильный URL: /search?q=rock%20%26%20roll — пробел становится %20, а амперсанд — %26.

Как работает процентное кодирование

Процентное кодирование преобразует байт в трёхсимвольную последовательность: знак процента и две заглавные шестнадцатеричные цифры, представляющие значение байта. Символ пробела (байт ASCII 32, шестнадцатеричный 0x20) становится %20. Символ «собачки» (@, ASCII 64, 0x40) становится %40. Правило:

percent-encode(byte) = "%" + byte.toString(16).toUpperCase().padStart(2, "0")

Примеры:
  пробел (0x20) → %20
  @      (0x40) → %40
  [      (0x5B) → %5B
  €      (UTF-8: 0xE2 0x82 0xAC) → %E2%82%AC

Для многобайтовых Unicode-символов (всё, что выходит за пределы ASCII) символ сначала кодируется в байты UTF-8, а затем каждый байт кодируется процентным кодированием. Знак евро — это три байта UTF-8, поэтому он превращается в три закодированных последовательности: %E2%82%AC.

Безопасные символы и зарезервированные символы

Не каждый символ нуждается в кодировании. RFC 3986 определяет два набора, безопасных для использования как есть:

  • Незарезервированные символы — A–Z, a–z, 0–9, дефис, подчёркивание, точка, тильда. Они не имеют специального смысла и никогда не требуют кодирования.
  • Зарезервированные символы: / ? # [ ] @ ! $ & ' ( ) * + , ; =. Они безопасны в своих структурных позициях, но должны кодироваться при появлении в значениях данных.

Всё остальное — пробелы, Unicode, управляющие символы, большинство знаков препинания — должно всегда кодироваться.

encodeURI против encodeURIComponent: критическое различие

JavaScript поставляется с двумя встроенными функциями кодирования, и путаница между ними является одной из самых распространённых ошибок URL-кодирования в веб-приложениях.

encodeURI() предназначен для кодирования полного URL. Он оставляет все зарезервированные символы нетронутыми, поскольку они структурно значимы в полном URL. Используйте его, если у вас есть полный URL, который может содержать пробелы или Unicode, но имеет правильную структуру:

encodeURI("https://example.com/search?q=hello world&lang=en")
// → "https://example.com/search?q=hello%20world&lang=en"
//   ✓ пробел закодирован, & и ? остались нетронутыми

encodeURIComponent() предназначен для кодирования одного значения — значения параметра запроса, сегмента пути, любых данных. Он кодирует и зарезервированные символы, включая &, =, ? и /:

encodeURIComponent("rock & roll")
// → "rock%20%26%20roll"
//   ✓ & закодирован — безопасно использовать как значение параметра запроса

encodeURIComponent("https://example.com/page")
// → "https%3A%2F%2Fexample.com%2Fpage"
//   ✓ двоеточия и слэши закодированы — безопасно как значение redirect_uri

Практическое правило: при построении URL используйте encodeURIComponent() для каждого отдельного значения параметра, но не для всего URL. Используйте encodeURI()только для полного URL, который нужно нормализовать. В современном коде предпочитайте API URL и URLSearchParams вместо ручного кодирования — они обрабатывают кодирование автоматически и корректно.

Подводные камни кодирования строки запроса

При кодировании строк запроса регулярно встречаются несколько тонких багов. Знак + заслуживает особого внимания: в формате application/x-www-form-urlencoded (формат, в котором HTML-формы отправляют данные) пробел кодируется как +, а не %20. Это устаревшее соглашение, предшествующее RFC 3986. Если бэкенд декодирует URL по правилам form-encoding, а фронтенд отправляет %20 — всё работает. Но если фронтенд отправляет +, а бэкенд декодирует по правилам RFC 3986, то + остаётся буквальным знаком плюс, а не пробелом.

// URLSearchParams использует application/x-www-form-urlencoded (+ для пробелов)
new URLSearchParams({ q: "rock & roll" }).toString()
// → "q=rock+%26+roll"

// encodeURIComponent использует RFC 3986 (%20 для пробелов)
"q=" + encodeURIComponent("rock & roll")
// → "q=rock%20%26%20roll"

// Оба варианта правильны — главное, чтобы оба конца были согласованы

Как данные формы кодируются в URL

Когда HTML-форма отправляется с method="GET", браузер сериализует поля формы в строку запроса, используя application/x-www-form-urlencoded. Каждое имя и значение поля кодируется (пробелы как +, специальные символы как %XX), а поля объединяются через &. Для форм с method="POST" без атрибута enctype используется то же кодирование, но данные помещаются в тело запроса, а не в URL.

Это также формат, который fetch() использует при передаче объекта URLSearchParams в качестве тела, и это то, что большинство серверных фреймворков автоматически декодируют при чтении отправок форм.

Base64 в URL

Стандартный Base64 использует + и / — оба символа имеют специальный смысл в URL. Когда Base64-кодированные данные должны появляться в URL (распространённый паттерн для токенов, данных изображений или криптографических подписей), вместо них используйте вариант Base64URL. Он заменяет + на -, а / на _, создавая строку, безопасную в любой позиции URL без дополнительного кодирования. JWT использует этот формат для сегментов заголовка и полезной нагрузки.

Реальные баги с кодированием

Несколько паттернов багов, встречающихся в продакшн-приложениях:

  • Двойное кодирование — кодирование уже закодированного URL. %20 становится %2520, потому что сам % кодируется в %25. Всегда проверяйте, не закодировано ли значение уже, прежде чем кодировать его снова.
  • Отсутствие encodeURIComponent для redirect_uri — OAuth-потоки передают redirect_uri как параметр запроса. Если он содержит ? или & и не закодирован, сервер авторизации разбирает эти символы как часть структуры внешнего URL, нарушая редирект.
  • Не-UTF-8 кодирование — старые системы или неправильно настроенные серверы иногда кодируют строки, используя ISO-8859-1 вместо UTF-8. Байтовые последовательности для é различаются. Всегда единообразно используйте UTF-8 с обеих сторон.
  • Логирование сырых URL — запись URL, содержащего закодированные пользовательские данные, может давать вводящие в заблуждение логи, если ваш просмотрщик логов автоматически декодирует процентные последовательности, скрывая то, что реально было передано по сети.

Мгновенное кодирование и декодирование URL

Отлаживаете ли вы OAuth-редирект, вручную строите строку запроса, проверяете сломанный запрос к API или просто хотите понять, что скрывается за процентно-закодированным URL — кодировщик/декодировщик URL BrowseryTools обработает это мгновенно. Вставьте строку, выберите кодирование или декодирование, и сразу увидите результат. Без серверных запросов, без регистрации.

Бесплатный кодировщик/декодировщик URL — работает на 100% в браузере

Открыть кодировщик URL →

🛠️

Try the Tools — 100% Free, No Sign-Up

Everything runs in your browser. No uploads. No accounts. No ads.

Explore All Tools →