URL Encode JavaScript — encodeURIComponent()
Використовуйте безкоштовний URL Encode Online прямо в браузері — без встановлення.
Спробувати URL Encode Online онлайн →Коли ви створюєте URL пошуку, передаєте шлях перенаправлення як параметр запиту або формуєте OAuth-запит авторизації, такі спеціальні символи, як &, = та пробіли, непомітно пошкодять URL, якщо попередньо не виконати URL-кодування. JavaScript пропонує три вбудовані підходи — encodeURIComponent(), encodeURI() та URLSearchParams — кожен з яких призначений для свого сценарію, і вибір неправильного методу є головною причиною більшості помилок кодування, з якими я стикався на код-рев'ю. Для швидкого одноразового кодування без написання коду URL Encoder ToolDeck обробляє це миттєво у браузері. Цей посібник детально розглядає всі три підходи (JavaScript ES2015+ / Node.js 10+): коли застосовувати кожен, чим вони відрізняються для пробілів та зарезервованих символів, реальні патерни з Fetch та API, використання в CLI і чотири помилки, що викликають найбільш підступні баги у продакшені.
- ✓encodeURIComponent() — правильний вибір для кодування значень окремих параметрів: він кодує всі символи, крім A–Z, a–z, 0–9 та - _ . ! ~ * ' ( )
- ✓encodeURI() кодує повний URL, зберігаючи структурні символи (/ ? # & = :) — ніколи не використовуйте його для окремих значень
- ✓URLSearchParams автоматично кодує пари ключ-значення у форматі application/x-www-form-urlencoded, де пробіли стають +, а не %20
- ✓Подвійне кодування — найпоширеніша помилка у продакшені: encodeURIComponent(encodeURIComponent(value)) перетворює %20 на %2520
- ✓Бібліотека qs нативно обробляє вкладені об'єкти та масиви у рядках запиту — стандартний URLSearchParams цього не вміє
Що таке URL-кодування?
URL-кодування (формально зване відсотковим кодуванням, визначено у RFC 3986) перетворює символи, недопустимі в URL або ті, що мають у ньому спеціальне значення, на безпечне представлення. Кожен небезпечний байт замінюється знаком відсотка, після якого стоять дві шістнадцяткові цифри — ASCII-код символу. Пробіл стає %20, амперсанд стає %26, коса риска стає %2F.
Символи, які завжди безпечні і ніколи не кодуються, називаються незарезервованими символами: літери A–Z та a–z, цифри 0–9 і чотири символи - _ . ~. Все інше або повинне бути закодоване при використанні як дані, або має структурну роль у самому URL (наприклад, / розділяє сегменти шляху, а &розділяє параметри запиту). Практичний наслідок: назва продукту на кшталт «Бездротова клавіатура & миша» у параметрі запиту зруйнує структуру URL, якщо передати її у сирому вигляді.
https://shop.example.com/search?q=Wireless Keyboard & Mouse&category=peripherals
https://shop.example.com/search?q=Wireless%20Keyboard%20%26%20Mouse&category=peripherals
encodeURIComponent() — правильна функція для параметрів запиту
encodeURIComponent() — основний інструмент URL-кодування у JavaScript. Він кодує кожен символ крім незарезервованого набору (A–Z, a–z, 0–9, - _ . ! ~ * ' ( )). Що особливо важливо, він кодує всі символи, що мають структурне значення у URL — &, =, ?, #, / — що робить його безпечним для використання у значеннях параметрів. Імпорт не потрібен: це глобальна функція, доступна у всіх JavaScript-середовищах.
Мінімальний робочий приклад
// Encode a search query parameter that contains special characters
const searchQuery = 'Wireless Keyboard & Mouse'
const filterStatus = 'in-stock'
const maxPrice = '149.99'
const searchUrl = `https://shop.example.com/products?` +
`q=${encodeURIComponent(searchQuery)}` +
`&status=${encodeURIComponent(filterStatus)}` +
`&maxPrice=${encodeURIComponent(maxPrice)}`
console.log(searchUrl)
// https://shop.example.com/products?q=Wireless%20Keyboard%20%26%20Mouse&status=in-stock&maxPrice=149.99Кодування URL перенаправлення як параметра запиту
// The redirect destination is itself a URL — it must be fully encoded
// or the outer URL parser will misinterpret its ? and & as its own
const redirectAfterLogin = 'https://dashboard.internal/reports?view=weekly&team=platform'
const loginUrl = `https://auth.company.com/login?next=${encodeURIComponent(redirectAfterLogin)}`
console.log(loginUrl)
// https://auth.company.com/login?next=https%3A%2F%2Fdashboard.internal%2Freports%3Fview%3Dweekly%26team%3Dplatform
// Decoding on the receiving end
const params = new URLSearchParams(window.location.search)
const next = params.get('next') // Automatically decoded
const nextUrl = new URL(next!) // Safe to parse
console.log(nextUrl.hostname) // dashboard.internalКодування символів не-ASCII та Unicode
// encodeURIComponent handles Unicode natively in all modern environments
// Each UTF-8 byte of the character is percent-encoded
const customerName = 'Іванченко, Олексій'
const productTitle = 'Київ wireless adapter'
const reviewText = 'Чудово — працює бездоганно'
console.log(encodeURIComponent(customerName))
// %D0%86%D0%B2%D0%B0%D0%BD%D1%87%D0%B5%D0%BD%D0%BA%D0%BE%2C%20%D0%9E%D0%BB%D0%B5%D0%BA%D1%81%D1%96%D0%B9
console.log(encodeURIComponent(productTitle))
// %D0%9A%D0%B8%D1%97%D0%B2%20wireless%20adapter
console.log(encodeURIComponent(reviewText))
// %D0%A7%D1%83%D0%B4%D0%BE%D0%B2%D0%BE%20%E2%80%94%20%D0%BF%D1%80%D0%B0%D1%86%D1%8E%D1%94%20%D0%B1%D0%B5%D0%B7%D0%B4%D0%BE%D0%B3%D0%B0%D0%BD%D0%BD%D0%BE
// Decoding back
console.log(decodeURIComponent('%D0%86%D0%B2%D0%B0%D0%BD%D1%87%D0%B5%D0%BD%D0%BA%D0%BE%2C%20%D0%9E%D0%BB%D0%B5%D0%BA%D1%81%D1%96%D0%B9'))
// Іванченко, ОлексійencodeURIComponent() використовує внутрішнє кодування рядків JavaScript UTF-16, а потім кодує кожен UTF-8 байт символу окремо. Символ і (U+0456), наприклад, кодується у %D1%96, оскільки його UTF-8 представлення складається з двох байтів: 0xD1 та 0x96. Це коректно і відповідає стандарту URI — сервери повинні декодувати послідовність байтів UTF-8 назад до вихідної кодової точки.Функції URL-кодування JavaScript — довідник по символах
Три нативні підходи до кодування відрізняються саме тим, які символи вони кодують. У таблиці нижче показано результат для найбільш проблематичних символів:
| Символ | Роль у URL | encodeURIComponent() | encodeURI() | URLSearchParams |
|---|---|---|---|---|
| Пробіл | роздільник слів | %20 | %20 | + |
| & | роздільник параметрів | %26 | kept | %26 |
| = | ключ=значення | %3D | kept | %3D |
| + | закодований пробіл (форма) | %2B | %2B | %2B |
| ? | початок запиту | %3F | kept | %3F |
| # | фрагмент | %23 | kept | %23 |
| / | роздільник шляху | %2F | kept | %2F |
| : | схема / порт | %3A | kept | %3A |
| @ | роздільник авторизації | %40 | kept | %40 |
| % | літерал відсотка | %25 | %25 | %25 |
| ~ | незарезервований | kept | kept | kept |
Ключова відмінність — стовпці encodeURIComponent() та encodeURI() для & та =: encodeURI() залишає їх незміненими, що правильно при кодуванні повного URL, але катастрофічно при кодуванні значення, що містить ці символи.
encodeURI() — коли потрібно зберегти структуру URL
encodeURI() призначений для кодування повного URL— він зберігає всі символи, що є допустимими структурними елементами URI: схему (https://), хост, роздільники шляху, роздільники запиту та ідентифікатор фрагмента. Використовуйте його, коли отримуєте URL, що може містити пробіли або не-ASCII символи у сегментах шляху, але потрібно зберегти його структуру незмінною.
Санітизація URL, наданого користувачем
// A URL pasted from a document with spaces in the path and non-ASCII chars const rawUrl = 'https://cdn.example.com/assets/product images/München chair.png' const safeUrl = encodeURI(rawUrl) console.log(safeUrl) // https://cdn.example.com/assets/product%20images/M%C3%BCnchen%20chair.png // encodeURIComponent would break it — it encodes the :// and all / characters const broken = encodeURIComponent(rawUrl) console.log(broken) // https%3A%2F%2Fcdn.example.com%2Fassets%2Fproduct%20images%2FM%C3%BCnchen%20chair.png // ↑ Not a valid URL — the scheme and slashes are destroyed
URL зазвичай є кращим вибором, ніж encodeURI(), для обробки рядків URL, введених користувачем — він нормалізує URL, перевіряє структуру і надає зручний API для доступу до кожного компонента. Залишіть encodeURI() для випадків, коли потрібен рядковий результат і ви вже знаєте, що вхідні дані структурно є коректним URL.URLSearchParams — сучасний підхід до рядків запиту
URLSearchParams — ідіоматичний спосіб побудови та розбору рядків запиту у сучасному JavaScript. Він доступний глобально у всіх сучасних браузерах і Node.js 10+, автоматично виконує кодування — ви працюєте зі звичайними парами ключ-значення, а він виробляє коректний результат. Важлива деталь: він дотримується специфікації application/x-www-form-urlencoded, яка кодує пробіли як +, а не %20. Це коректно і широко підтримується, але слід враховувати це, коли ваш сервер очікує конкретний формат.
Побудова URL пошукового запиту
// Building a search API URL with multiple parameters
const filters = {
query: 'standing desk',
category: 'office-furniture',
minPrice: '200',
maxPrice: '800',
inStock: 'true',
sortBy: 'price_asc',
}
const params = new URLSearchParams(filters)
const apiUrl = `https://api.example.com/v2/products?${params}`
console.log(apiUrl)
// https://api.example.com/v2/products?query=standing+desk&category=office-furniture&minPrice=200&maxPrice=800&inStock=true&sortBy=price_asc
// Appending additional params after construction
params.append('page', '2')
params.append('tag', 'ergonomic & adjustable')
console.log(params.toString())
// query=standing+desk&...&tag=ergonomic+%26+adjustableРозбір вхідного рядка запиту
// Both browser (window.location.search) and Node.js (req.url) scenarios
function parseWebhookCallbackUrl(rawSearch: string) {
const params = new URLSearchParams(rawSearch)
return {
eventId: params.get('event_id'), // null if missing
timestamp: Number(params.get('ts')),
signature: params.get('sig'),
redirectUrl: params.get('redirect'), // Automatically decoded
tags: params.getAll('tag'), // Handles repeated keys
}
}
const callbackQuery = '?event_id=evt_9c2f&ts=1717200000&sig=sha256%3Dabc123&redirect=https%3A%2F%2Fdashboard.internal%2F&tag=payment&tag=webhook'
const parsed = parseWebhookCallbackUrl(callbackQuery)
console.log(parsed.redirectUrl) // https://dashboard.internal/
console.log(parsed.tags) // ['payment', 'webhook']Як URL-кодувати параметри у Fetch-запитах JavaScript
Найчастіше URL-кодування зустрічається у продакшен-коді всередині викликів fetch() — або при побудові URL запиту, або при надсиланні даних форми у тілі запиту. Кожен сценарій має свій коректний підхід.
GET-запит — кодування параметрів запиту
async function searchInventory(params: {
sku?: string
warehouse: string
minStock: number
updatedAfter?: Date
}): Promise<{ items: unknown[]; total: number }> {
const searchParams = new URLSearchParams()
if (params.sku) searchParams.set('sku', params.sku)
searchParams.set('warehouse', params.warehouse)
searchParams.set('min_stock', String(params.minStock))
if (params.updatedAfter) searchParams.set('updated_after', params.updatedAfter.toISOString())
const url = `https://inventory.internal/api/items?${searchParams}`
const res = await fetch(url, {
headers: {
'Authorization': `Bearer ${process.env.INVENTORY_API_KEY}`,
'Accept': 'application/json',
},
})
if (!res.ok) {
throw new Error(`Inventory API ${res.status}: ${await res.text()}`)
}
return res.json()
}
const results = await searchInventory({
warehouse: 'eu-west-1',
minStock: 10,
updatedAfter: new Date('2025-01-01'),
})
console.log(`Found ${results.total} items`)POST-запит — URL-кодування тіла форми
// application/x-www-form-urlencoded POST — used by OAuth token endpoints,
// legacy form-submission APIs, and some webhook providers
async function requestOAuthToken(
clientId: string,
clientSecret: string,
code: string,
redirectUri: string,
): Promise<{ access_token: string; expires_in: number }> {
const body = new URLSearchParams({
grant_type: 'authorization_code',
client_id: clientId,
client_secret: clientSecret,
code,
redirect_uri: redirectUri, // URLSearchParams encodes this automatically
})
const res = await fetch('https://oauth.provider.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body.toString(),
// body: body — also works directly in modern environments (Fetch spec accepts URLSearchParams)
})
if (!res.ok) {
const err = await res.json()
throw new Error(`OAuth error: ${err.error_description ?? err.error}`)
}
return res.json()
}Коли потрібно перевірити або відлагодити закодований URL без написання скрипту, вставте вихідне значення прямо у URL Encoder — він миттєво кодує і декодує, показуючи саме те, що побачать браузер і сервер. Зручно для перевірки OAuth redirect URI, URL зворотних викликів вебхуків і параметрів підписаних запитів CDN.
URL-кодування у командному рядку з Node.js та Shell
Для shell-скриптів, CI-пайплайнів або швидкого налагодження існує кілька підходів командного рядка, які не потребують написання повного скрипту.
# ── Node.js one-liners — cross-platform (macOS, Linux, Windows) ────────
# encodeURIComponent — encode a single value
node -e "console.log(encodeURIComponent(process.argv[1]))" "Wireless Keyboard & Mouse"
# Wireless%20Keyboard%20%26%20Mouse
# Build a complete query string
node -e "console.log(new URLSearchParams(JSON.parse(process.argv[1])).toString())" '{"q":"standing desk","category":"office-furniture","page":"1"}'
# q=standing+desk&category=office-furniture&page=1
# Decode a percent-encoded string
node -e "console.log(decodeURIComponent(process.argv[1]))" "Wireless%20Keyboard%20%26%20Mouse"
# Wireless Keyboard & Mouse
# ── curl — automatic encoding ───────────────────────────────────────────
# curl --data-urlencode encodes values automatically in GET and POST
curl -G "https://api.example.com/search" --data-urlencode "q=Wireless Keyboard & Mouse" --data-urlencode "category=office furniture"
# ── Python one-liner (available on most systems) ─────────────────────────
python3 -c "from urllib.parse import quote; print(quote(input(), safe=''))"
# (type the string and press Enter)
# ── jq + bash: encode every value in a JSON object ───────────────────────
echo '{"q":"hello world","tag":"node & express"}' | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(new URLSearchParams(d).toString())"
# q=hello+world&tag=node+%26+expressВисокопродуктивна альтернатива: qs
Вбудований URLSearchParams не підтримує вкладені об'єкти та масиви — формат рядків запиту, що використовується багатьма API і фреймворками. Бібліотека qs (30M+ щотижневих завантажень з npm) обробляє повний спектр паттернів рядків запиту: вкладені об'єкти зі скобочною нотацією (filters[status]=active), повторювані ключі, користувацькі кодувальники і настроювані формати серіалізації масивів.
npm install qs # or pnpm add qs
import qs from 'qs'
// URLSearchParams cannot represent this structure natively
const reportFilters = {
dateRange: {
from: '2025-01-01',
to: '2025-03-31',
},
status: ['published', 'archived'],
author: { id: 'usr_4f2a9c1b', role: 'editor' },
workspace: 'ws-platform-eu',
}
// qs produces bracket-notation query strings used by Express, Rails, Django REST
const query = qs.stringify(reportFilters, { encode: true })
console.log(query)
// dateRange%5Bfrom%5D=2025-01-01&dateRange%5Bto%5D=2025-03-31&status%5B0%5D=published&status%5B1%5D=archived&author%5Bid%5D=usr_4f2a9c1b&author%5Brole%5D=editor&workspace=ws-platform-eu
// Human-readable (no encoding) — useful for debugging
console.log(qs.stringify(reportFilters, { encode: false }))
// dateRange[from]=2025-01-01&dateRange[to]=2025-03-31&status[0]=published&status[1]=archived...
// Parsing back
const parsed = qs.parse(query)
console.log(parsed.dateRange) // { from: '2025-01-01', to: '2025-03-31' }
console.log(parsed.status) // ['published', 'archived']Для плоских параметрів ключ-значення URLSearchParams — завжди правильний вибір: він вбудований, не має накладних витрат і універсально підтримується. Звертайтеся до qs лише тоді, коли потрібні вкладені структури, формати серіалізації масивів, відмінні від повторюваних ключів, або ви інтегруєтеся з бекенд-фреймворком, що очікує рядки запиту у скобочній нотації.
Поширені помилки
Я неодноразово бачив ці чотири помилки у продакшен-кодових базах — більшість з них є прихованими збоями, що проявляються лише тоді, коли значення містить спеціальний символ, що саме той вид багів, які проходять крізь юніт-тести і з'являються лише з реальними користувацькими даними.
Помилка 1 — Використання encodeURI() для значень параметрів запиту
Проблема: encodeURI() не кодує &, = та +. Коли значення містить ці символи, вони інтерпретуються як синтаксис рядка запиту, непомітно розбиваючи або перезаписуючи параметри. Виправлення: завжди використовуйте encodeURIComponent() для окремих значень.
// ❌ encodeURI does not encode & and = in the value
// "plan=pro&promo=SAVE20" is treated as two separate params
const planName = 'Pro Plan (save=20% & free trial)'
const url = `/checkout?plan=${encodeURI(planName)}`
// /checkout?plan=Pro%20Plan%20(save=20%%20&%20free%20trial)
// ↑ & breaks the query string// ✅ encodeURIComponent encodes & and = safely
const planName = 'Pro Plan (save=20% & free trial)'
const url = `/checkout?plan=${encodeURIComponent(planName)}`
// /checkout?plan=Pro%20Plan%20(save%3D20%25%20%26%20free%20trial)
// ↑ = and & are both encodedПомилка 2 — Подвійне кодування вже закодованого рядка
Проблема: Виклик encodeURIComponent() для значення, яке вже закодоване відсотками, перетворює % на %25, тому %20 стає %2520. Сервер декодує один раз і отримує буквальний %20 замість пробілу. Виправлення: спочатку декодуйте, потім перекодуйте, або переконайтеся, що значення ніколи не кодується двічі.
// ❌ encodedParam already contains %20 — encoding again produces %2520
const encodedParam = 'Berlin%20Office'
const url = `/api/locations/${encodeURIComponent(encodedParam)}`
// /api/locations/Berlin%2520Office
// Server sees: "Berlin%20Office" (a literal percent-twenty, not a space)// ✅ Decode first if the value may already be encoded
const maybeEncoded = 'Berlin%20Office'
const clean = decodeURIComponent(maybeEncoded) // 'Berlin Office'
const url = `/api/locations/${encodeURIComponent(clean)}`
// /api/locations/Berlin%20Office — correctПомилка 3 — Ігнорування різниці між + та %20 у URLSearchParams і encodeURIComponent
Проблема: URLSearchParams кодує пробіли як + (application/x-www-form-urlencoded), тоді як encodeURIComponent() використовує %20. Змішування обох підходів в одному URL — наприклад, додавання попередньо закодованого рядка до виводу URLSearchParams — створює непослідовне кодування, що збиває з пантелику деякі парсери. Виправлення: виберіть один підхід і послідовно застосовуйте його у всій функції побудови URL.
// ❌ Mixed: URLSearchParams uses + for spaces, but we're appending
// a manually-encoded segment that uses %20
const base = new URLSearchParams({ category: 'office furniture' })
const extra = `sort=${encodeURIComponent('price asc')}`
const url = `/api/products?${base}&${extra}`
// /api/products?category=office+furniture&sort=price%20asc
// ↑ two different space encodings in the same URL// ✅ Use URLSearchParams exclusively — consistent encoding throughout
const params = new URLSearchParams({
category: 'office furniture',
sort: 'price asc',
})
const url = `/api/products?${params}`
// /api/products?category=office+furniture&sort=price+ascПомилка 4 — Забути закодувати сегменти шляху, що містять косі риски
Проблема: Ідентифікатор ресурсу на кшталт шляху до файлу (reports/2025/q1.pdf), що використовується як сегмент шляху REST, містить символи /, які маршрутизатор сервера інтерпретує як роздільники шляху, направляючи запит до неіснуючого кінцевого адресу. Виправлення: завжди використовуйте encodeURIComponent() для сегментів шляху, що можуть містити косі риски.
// ❌ The file path contains / — the server receives a 3-segment path
// instead of a single resource ID
const filePath = 'reports/2025/q1-financials.pdf'
const url = `https://storage.example.com/objects/${filePath}`
// https://storage.example.com/objects/reports/2025/q1-financials.pdf
// → Server routes to /objects/:year/:filename — 404 or wrong resource// ✅ encodeURIComponent encodes / as %2F — single path segment
const filePath = 'reports/2025/q1-financials.pdf'
const url = `https://storage.example.com/objects/${encodeURIComponent(filePath)}`
// https://storage.example.com/objects/reports%2F2025%2Fq1-financials.pdf
// → Server receives the full file path as one resource identifierМетоди URL-кодування JavaScript — швидке порівняння
| Метод | Кодує пробіли як | Кодує & = ? | Кодує # / : | Сценарій використання | Потребує встановлення |
|---|---|---|---|---|---|
| encodeURIComponent() | %20 | ✅ так | ✅ так | Кодування окремих значень параметрів | No |
| encodeURI() | %20 | ❌ ні | ❌ ні | Санітизація повного рядка URL | No |
| URLSearchParams | + | ✅ так | ✅ так | Побудова та розбір рядків запиту | No |
| Конструктор URL | авто по компоненту | авто | авто | Конструювання та нормалізація повних URL | No |
| Бібліотека qs | %20 (настроювано) | ✅ так | ✅ так | Вкладені об'єкти та масиви у рядках запиту | npm install qs |
У переважній більшості випадків вибір зводиться до трьох сценаріїв. Використовуйте URLSearchParams при побудові багатопараметричних рядків запиту зі структурованих даних — це найбезпечніший та найчитабельніший варіант. Використовуйте encodeURIComponent() для кодування одного значення у шаблонному URL, для сегментів шляху або для значень у системах, що очікують %20 замість + для пробілів (наприклад, підписані URL AWS S3). Звертайтеся до qs лише тоді, коли рядок запиту містить вкладені об'єкти або масиви, які URLSearchParams не може представити нативно.
Часті запитання
Пов'язані інструменти
Для швидкого кодування або декодування без написання коду вставте ваш рядок прямо у URL Encoder — він миттєво виконує відсоткове кодування та декодування у вашому браузері, з готовим результатом для копіювання у виклик fetch або термінал.
Alex is a front-end and Node.js developer with extensive experience building web applications and developer tooling. He is passionate about web standards, browser APIs, and the JavaScript ecosystem. In his spare time he contributes to open-source projects and writes about modern JavaScript patterns, performance optimisation, and everything related to the web platform.
Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.