Справочный раздел

URL и percent-encoding: символы, query-параметры и примеры

Структура URL, зарезервированные символы RFC 3986, UTF-8 percent-encoding, query-параметры и примеры URLSearchParams.

18 символов
RFC 398618зарезервированных символов
Безопасный наборA–ZA–Z · a–z · 0–9 · - . _ ~
КодировкаUTF‑8один triplet %HH на байт
Сначала разберите адрес

URL состоит из отдельных компонентов

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

  1. СхемаhttpsВыбирает протокол.
  2. Hostexample.comНазывает сервер; домен сериализуется отдельно от текста пути.
  3. Порт443Необязательный сетевой порт после host.
  4. Путь/catalog/caf%C3%A9Последовательность сегментов, разделённых косой чертой.
  5. Query?q=coffee&tag=urlДанные приложения в виде имён и значений после ?.
  6. Fragment#examplesПозиция или состояние на клиенте после #; обычно не отправляется в HTTP.
RFC 3986

Зарезервированные символы и их percent-форма

Зарезервированный знак можно оставить как есть, когда он выполняет роль разделителя. Если это данные внутри компонента, кодируйте знак, чтобы он не изменил структуру URL.

Зарезервированные символы URL по RFC 3986
СимволГруппаHEXPercentТипичная роль
:Двоеточие
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-параметра от значения.
UTF‑8 → %HH

Примеры percent-encoding

Сначала символ превращается в байты UTF-8, затем каждый кодируемый байт записывается как % и две шестнадцатеричные цифры.

Примеры 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.
application/x-www-form-urlencoded

Собирайте 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 браузера использовать

new URL()целый URL

Разбирает, разрешает и сериализует полный URL. Для пути, query и fragment используйте отдельные свойства pathname, searchParams и hash.

const url = new URL("/search", "https://example.com");
URLSearchParamsquery

Собирает и читает пары query. Использует application/x-www-form-urlencoded: пробел становится +, а буквальный плюс — %2B.

new URLSearchParams({ q: "кофе & чай" }).toString()
encodeURIComponent()один компонент

Кодирует текст, который станет одним компонентом URL. Пробел превращается в %20; не применяйте функцию к уже собранному URL.

encodeURIComponent("a/b?c=d") // a%2Fb%3Fc%3Dd
encodeURI()текст целого URI

Сохраняет разделители /, ?, #, & и =. Не делает небезопасную query-строку пригодной для конкатенации.

encodeURI("https://example.com/a b?q=x")
Первоисточники

Стандарты, на которых основаны таблицы

Связанные инструменты

Продолжите работу с текстом

Скопируйте символ, преобразуйте разметку, очистите фрагмент или сохраните результат в блокноте.

FAQ

Вопросы о кодировании 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.