URL и percent-encoding: символы, query-параметры и примеры
Структура URL, зарезервированные символы RFC 3986, UTF-8 percent-encoding, query-параметры и примеры URLSearchParams.
URL состоит из отдельных компонентов
Один знак может быть синтаксисом в одном компоненте и обычными данными в другом. Кодируйте значение на границе, где оно вставляется.
- Схема
httpsВыбирает протокол. - Host
example.comНазывает сервер; домен сериализуется отдельно от текста пути. - Порт
443Необязательный сетевой порт после host. - Путь
/catalog/caf%C3%A9Последовательность сегментов, разделённых косой чертой. - Query
?q=coffee&tag=urlДанные приложения в виде имён и значений после ?. - Fragment
#examplesПозиция или состояние на клиенте после #; обычно не отправляется в HTTP.
Зарезервированные символы и их percent-форма
Зарезервированный знак можно оставить как есть, когда он выполняет роль разделителя. Если это данные внутри компонента, кодируйте знак, чтобы он не изменил структуру URL.
Подходящих зарезервированных символов не найдено.
| Символ | Группа | HEX | Percent | Типичная роль |
|---|---|---|---|---|
:Двоеточие | gen-delims | 3A | Отделяет схему, порт и части userinfo. | |
/Косая черта | gen-delims | 2F | Разделяет сегменты пути; две черты вводят authority. | |
?Вопросительный знак | gen-delims | 3F | Начинает query-часть URL. | |
#Решётка | gen-delims | 23 | Начинает фрагмент; на сервер обычно не отправляется. | |
[Левая квадратная скобка | gen-delims | 5B | Открывает литерал IPv6 в host. | |
]Правая квадратная скобка | gen-delims | 5D | Закрывает литерал IPv6 в host. | |
@Знак @ | gen-delims | 40 | Отделяет userinfo от host. | |
!Восклицательный знак | sub-delims | 21 | Подразделитель; точный смысл задаёт схема или компонент. | |
$Знак доллара | sub-delims | 24 | Подразделитель; может иметь специальный смысл в конкретной схеме. | |
&Амперсанд | sub-delims | 26 | Обычно разделяет пары query-параметров. | |
'Апостроф | sub-delims | 27 | Подразделитель без универсального значения. | |
(Левая круглая скобка | sub-delims | 28 | Подразделитель без универсального значения. | |
)Правая круглая скобка | sub-delims | 29 | Подразделитель без универсального значения. | |
*Звёздочка | sub-delims | 2A | Подразделитель; URLSearchParams обычно оставляет его как *. | |
+Знак плюс | sub-delims | 2B | В form-urlencoded обозначает пробел; буквальный плюс кодируют как %2B. | |
,Запятая | sub-delims | 2C | Подразделитель; значение зависит от API или схемы. | |
;Точка с запятой | sub-delims | 3B | Подразделитель; иногда разделяет параметры сегмента пути. | |
=Знак равенства | sub-delims | 3D | Обычно отделяет имя query-параметра от значения. |
Примеры percent-encoding
Сначала символ превращается в байты UTF-8, затем каждый кодируемый байт записывается как % и две шестнадцатеричные цифры.
| Исходное | UTF‑8 | Результат | Зачем |
|---|---|---|---|
SPПробел | 20 | В URLSearchParams становится +. | |
+Литеральный плюс | 2B | Нужно отличать от пробела в form-urlencoded. | |
&Амперсанд в значении | 26 | Иначе выглядит как разделитель параметров. | |
=Равенство в значении | 3D | Иначе может выглядеть как граница имени и значения. | |
/Косая черта как данные | 2F | Внутри одного компонента не должна делить путь. | |
#Решётка как данные | 23 | Иначе начинает fragment. | |
%Знак процента | 25 | Начинает percent-triplet и сам кодируется. | |
éЛатинская é | C3 A9 | Два байта UTF-8 — два triplet. | |
яКириллическая я | D1 8F | Кодируется по байтам UTF-8. | |
😀Эмодзи | F0 9F 98 80 | Четыре байта UTF-8 — четыре triplet. |
Собирайте query-параметры как пары
Не склеивайте пользовательские данные вручную через &, = и +. URLSearchParams сохраняет границу имени и значения и поддерживает повторяющиеся ключи.
const url = new URL("https://example.com/search");
url.searchParams.set("q", "кофе & чай");
url.searchParams.append("tag", "url");
url.searchParams.append("tag", "encoding");
url.toString(); params.get("tag")возвращает только первое значение
params.getAll("tag")возвращает ["url", "encoding"]
params.has("debug")проверяет наличие отдельно от значения
decodeURIComponent("a+b")возвращает a+b, а не пробел; для form-query используйте URLSearchParams
Какой API браузера использовать
Разбирает, разрешает и сериализует полный URL. Для пути, query и fragment используйте отдельные свойства pathname, searchParams и hash.
const url = new URL("/search", "https://example.com");Собирает и читает пары query. Использует application/x-www-form-urlencoded: пробел становится +, а буквальный плюс — %2B.
new URLSearchParams({ q: "кофе & чай" }).toString()Кодирует текст, который станет одним компонентом URL. Пробел превращается в %20; не применяйте функцию к уже собранному URL.
encodeURIComponent("a/b?c=d") // a%2Fb%3Fc%3DdСохраняет разделители /, ?, #, & и =. Не делает небезопасную query-строку пригодной для конкатенации.
encodeURI("https://example.com/a b?q=x")Стандарты, на которых основаны таблицы
Продолжите работу с текстом
Скопируйте символ, преобразуйте разметку, очистите фрагмент или сохраните результат в блокноте.
- Кодировать и декодировать HTML-сущности Преобразуйте спецсимволы в безопасные HTML-сущности и обратно.
- Конвертировать Markdown в HTML Подготовьте HTML-разметку из Markdown-черновика.
- Удалить HTML-теги Оставьте читаемый текст без разметки.
- Изменить регистр текста Переведите буквы в верхний или нижний регистр.
- Открыть онлайн-блокнот Используйте скопированные символы в локальной заметке.
Вопросы о кодировании URL
Почему пробел становится то %20, то +?
%20 — percent-encoding UTF-8-байта пробела. Формат application/x-www-form-urlencoded, который использует URLSearchParams, сериализует пробел как +. Оба варианта встречаются в query, но + не заменяет пробел во всех компонентах URL.
Как передать буквальный плюс в query-значении?
Используйте URLSearchParams или кодируйте плюс как %2B. Query-парсер в стиле HTML-формы прочитает необработанный + как пробел.
Нужно ли кодировать целый URL через encodeURIComponent()?
Нет. Функция закодирует структурные разделители и превратит весь URL в один компонент. Для целого адреса используйте new URL(), а URLSearchParams или encodeURIComponent() — только на границе конкретного значения.
Могут ли query-параметры повторяться?
Да. Query — упорядоченный список пар имя/значение, поэтому tag=url&tag=encoding допустим. Добавляйте значения через append(), а читайте все повторения через getAll().
В percent-triplet нужны заглавные HEX-цифры?
Регистр HEX-цифр не влияет на декодирование, но RFC 3986 рекомендует для нормализации заглавные A–F: например, %2F вместо %2f.