URL Decode JavaScript — decodeURIComponent()
Använd det kostnadsfria URL Decode Online direkt i webbläsaren — ingen installation krävs.
Prova URL Decode Online online →Procentkodade strängar förekommer ständigt i JavaScript-kod — en sökfråga anländer som q=standing+desk%26price%3A200, en OAuth-omdirigering som next=https%3A%2F%2Fdashboard.internal%2F, en lagringssökväg som reports%2F2025%2Fq1.pdf. Att URL-avkoda i JavaScript handlar om att välja rätt av tre inbyggda funktioner: decodeURIComponent(), decodeURI() och URLSearchParams — och valet mellan dem är grundorsaken till den tysta datakorruption jag sett i produktionskod, särskilt kantfallet +-som-mellanslag och dubbelavkodning. För snabb engångsavkodning utan att skriva kod hanterar ToolDecks URL Decoder det direkt i webbläsaren. Den här handledningen för JavaScript URL-avkodning täcker alla tre funktionerna på djupet (ES2015+ / Node.js 10+): när man använder vilken, hur de skiljer sig för mellanslag och reserverade tecken, avkodning från filer och HTTP-förfrågningar, säker felhantering och de fyra misstagen som orsakar flest subtila produktionsproblem.
- ✓decodeURIComponent() avkodar alla procentkodade sekvenser — det är rätt val för enskilda frågeparametervärden och sökvägssegment
- ✓decodeURI() bevarar strukturella URI-tecken som / ? & = # : — använd det bara när du avkodar en hel URL-sträng, aldrig för enskilda värden
- ✓URLSearchParams.get() returnerar redan avkodade värden — att anropa decodeURIComponent() på dess utdata orsakar dubbelavkodning
- ✓decodeURIComponent() avkodar INTE + som mellanslag — för formkodad data (application/x-www-form-urlencoded), använd URLSearchParams eller ersätt + innan avkodning
- ✓Omslut alltid decodeURIComponent() med try/catch när indata kommer från användardata — ett ensamt % eller en ofullständig sekvens kastar ett URIError
Vad är URL-avkodning?
Procentkodning (formellt definierat i RFC 3986) ersätter tecken som är osäkra eller strukturellt betydelsefulla i en URL med ett %-tecken följt av två hexadecimala siffror — tecknet UTF-8-bytevärde. URL-avkodning vänder på den transformationen: varje %XX-sekvens konverteras tillbaka till sin ursprungliga byte, och den resulterande bytesekvensen tolkas som UTF-8-text. Ett mellanslag avkodat från %20, ett snedstreck från %2F, det icke-ASCII-tecknet ü från %C3%BC (dess tvåbytes UTF-8-representation).
Tecknen som aldrig kodas — kallade oreskrverade tecken — är bokstäverna A–Z och a–z, siffrorna 0–9 och - _ . ~. Allt annat har antingen en strukturell roll i URL:en (som / för att separera sökvägssegment eller & för att separera frågeparametrar) eller måste kodas när det används som datavärde. Det praktiska resultatet: ett sökfilter som status=active&tier=premium kodat som ett enda frågeparametervärde ser ut helt annorlunda än originalet vid ankomst.
// Procentkodat — som mottaget i en HTTP-förfrågan eller webhook-nyttolast "q=price%3A%5B200+TO+800%5D%20AND%20brand%3ANorthwood%20%26%20status%3Ain-stock"
// Efter URL-avkodning — det ursprungliga Elasticsearch-frågefiltret "q=price:[200 TO 800] AND brand:Northwood & status:in-stock"
decodeURIComponent() — Standardfunktionen för att avkoda värden
decodeURIComponent() är arbetshästen för URL-avkodning i JavaScript. Den avkodar varje %XX-sekvens i inmatningssträngen — inklusive tecken med strukturell betydelse i en URL, som %2F (snedstreck), %3F (frågetecken), %26 (et-tecken) och %3D (likhetstecken). Det gör det till rätt val för att avkoda enskilda frågeparametervärden och sökvägssegment, men fel val för att avkoda en komplett URL — där dessa strukturella tecken måste förbli kodade. Det är en global funktion: ingen import behövs i någon JavaScript-miljö.
Minimalt fungerande exempel
// Avkoda enskilda frågeparametervärden — det vanliga fallet
const city = decodeURIComponent('S%C3%A3o%20Paulo') // 'São Paulo'
const district = decodeURIComponent('It%C3%A1im%20Bibi') // 'Itáim Bibi'
const category = decodeURIComponent('office%20furniture') // 'office furniture'
const filter = decodeURIComponent('price%3A%5B200+TO+800%5D') // 'price:[200+TO+800]'
// Obs: + avkodas INTE som mellanslag — se +-avsnittet i jämförelsetabellen
console.log(city) // São Paulo
console.log(district) // Itáim Bibi
console.log(category) // office furniture
console.log(filter) // price:[200+TO+800]Avkoda en omdirigerings-URL extraherad från en frågeparameter
// Omdirigerings-URL:en var procentkodad när den bäddades in som ett parametervärde
// mottagarsidan: extrahera den, använd den sedan — ingen manuell avkodning behövs med URLSearchParams
const incomingUrl = 'https://auth.company.com/callback' +
'?next=https%3A%2F%2Fdashboard.internal%2Freports%3Fview%3Dweekly%26team%3Dplatform' +
'&session_id=sid_7x9p2k'
const url = new URL(incomingUrl)
const rawNext = url.searchParams.get('next') // Automatiskt avkodat av URLSearchParams
const sessionId = url.searchParams.get('session_id') // 'sid_7x9p2k'
// rawNext är redan avkodat: 'https://dashboard.internal/reports?view=weekly&team=platform'
// Anropa INTE decodeURIComponent(rawNext) igen — det skulle vara dubbelavkodning
const nextUrl = new URL(rawNext!)
console.log(nextUrl.hostname) // dashboard.internal
console.log(nextUrl.searchParams.get('view')) // weekly
console.log(nextUrl.searchParams.get('team')) // platformAvkoda icke-ASCII- och Unicode-sökvägssegment
// REST API med internationaliserade sökvägssegment
// Varje UTF-8-byte hos det ursprungliga tecknet kodades separat
const encodedSegments = [
'%E6%9D%B1%E4%BA%AC', // 東京 (Tokyo) — 3 bytes per tecken
'M%C3%BCnchen', // München — ü kodat som 2 bytes
'caf%C3%A9', // café — é som förkomponerat NFC
'S%C3%A3o%20Paulo', // São Paulo
]
encodedSegments.forEach(seg => {
console.log(decodeURIComponent(seg))
})
// 東京
// München
// café
// São Paulo
// Extrahera en filnyckel från en lagrings-API-URL
// Objektnyckeln innehöll ett / så den kodades som %2F inuti sökvägssegmentet
const storageUrl = 'https://storage.api.example.com/v1/objects/reports%2F2025%2Fq1-financials.pdf'
const rawKey = new URL(storageUrl).pathname.replace('/v1/objects/', '')
// .pathname avkodar URL-nivåkodning men %2F (som %252F på URL-nivå) stannar kvar
// Använd decodeURIComponent för det sista steget:
const fileKey = decodeURIComponent(rawKey) // 'reports/2025/q1-financials.pdf'
console.log(fileKey)decodeURIComponent() kastar ett URIError när indata innehåller ett % som inte följs av två giltiga hexadecimala siffror — till exempel ett ensamt % i slutet av en sträng eller en sekvens som %GH. Omslut det alltid med try/catch vid avkodning av användaruppgiven indata. Säkra avkodningsmönster täcks i avsnittet Felhantering nedan.JavaScript URL-avkodningsfunktioner — Teckensreferens
De tre inbyggda avkodningsfunktionerna skiljer sig i exakt vilka kodade sekvenser de avkodar. Tabellen visar beteendet för de tecken som spelar störst roll i praktiken:
| Kodat | Tecken | decodeURIComponent() | decodeURI() | URLSearchParams |
|---|---|---|---|---|
| %20 | mellanslag | mellanslag ✅ | mellanslag ✅ | mellanslag ✅ |
| + | plus (form) | + (bevarat) | + (bevarat) | mellanslag ✅ |
| %2B | + literal | + ✅ | + ✅ | + ✅ |
| %26 | & | & ✅ | & (bev.) ❌ | & ✅ |
| %3D | = | = ✅ | = (bev.) ❌ | = ✅ |
| %3F | ? | ? ✅ | ? (bev.) ❌ | ? ✅ |
| %23 | # | # ✅ | # (bev.) ❌ | # ✅ |
| %2F | / | / ✅ | / (bev.) ❌ | / ✅ |
| %3A | : | : ✅ | : (bev.) ❌ | : ✅ |
| %40 | @ | @ ✅ | @ (bev.) ❌ | @ ✅ |
| %25 | % | % ✅ | % ✅ | % ✅ |
| %C3%BC | ü | ü ✅ | ü ✅ | ü ✅ |
De två kritiska raderna är + och de strukturella tecknen (%26, %3D, %3F). URLSearchParams avkodar + som ett mellanslag eftersom det följer specifikationen application/x-www-form-urlencoded — korrekt för HTML-formulärsinlämningar, men annorlunda än vad decodeURIComponent() gör med samma tecken. Och decodeURI() hoppar tyst över %26, %3D och %3F — vilket ser korrekt ut tills ett värde faktiskt innehåller ett kodat et-tecken eller likhetstecken.
decodeURI() — Avkoda en komplett URL utan att förstöra dess struktur
decodeURI() är motparten till encodeURI(). Den avkodar en komplett URL-sträng och bevarar tecken med strukturell betydelse i en URI: ; , / ? : @ & = + $ #. Dessa lämnas i sin procentkodade form (eller som bokstavliga tecken om de förekom okodade i indata). Det gör decodeURI() säker för sanering av fullständiga URL:er som kan innehålla icke-ASCII-tecken i sökvägen eller värdnamnet, utan att råka kollapsa frågesträngsstrukturen.
Sanera en URL med icke-ASCII-sökvägssegment
// En CDN-URL med internationaliserade sökvägssegment och en strukturerad frågesträng // decodeURI() avkodar icke-ASCII-sökväg men bevarar ? & = intakt const encodedUrl = 'https://cdn.example.com/assets/%E6%9D%B1%E4%BA%AC%2F2025%2Fq1-report.pdf' + '?token=eyJ0eXAiOiJKV1QiLCJhbGci&expires=1735689600' const readable = decodeURI(encodedUrl) console.log(readable) // https://cdn.example.com/assets/東京/2025/q1-report.pdf?token=eyJ0eXAiOiJKV1QiLCJhbGci&expires=1735689600 // ↑ Icke-ASCII avkodat; ? & = bevarat — URL förblir strukturellt giltig // decodeURIComponent skulle förstöra URL:en — : / ? & = avkodas alla på en gång const broken = decodeURIComponent(encodedUrl) // Ser likadant ut här, men en URL som 'https%3A%2F%2F...' skulle förstöras
URL-konstruktorn framför decodeURI() när du också behöver åtkomst till enskilda URL-komponenter. new URL(str) normaliserar indata, validerar strukturen och exponerar .pathname, .searchParams och .hostname som redan avkodade egenskaper. Reservera decodeURI() för fall där du bara behöver ett strängresultat och inte kan använda URL-konstruktorn (till exempel i mycket gamla Node.js 6-miljöer utan den globala URL-klassen).URLSearchParams — Automatisk avkodning för frågesträngar
URLSearchParams är det idiomatiska sättet att analysera frågesträngar i modern JavaScript. Varje värde som returneras av .get(), .getAll() eller iteration är automatiskt avkodat — inklusive + som mellanslag för formkodad data. Det är globalt tillgängligt i alla moderna webbläsare och Node.js 10+, kräver ingen import och hanterar kantfall som manuell strängdelning gör fel.
Analysera en inkommande frågesträng
// Analysera en webhook-callback eller OAuth-omdirigeringsfrågesträng
const rawSearch =
'?event_id=evt_9c2f4a1b' +
'&product_name=Standing+Desk+Pro' +
'&filter=price%3A%5B200+TO+800%5D' +
'&tag=ergonomic&tag=adjustable' +
'&redirect=https%3A%2F%2Fdashboard.internal%2Forders%3Fview%3Dpending'
const params = new URLSearchParams(rawSearch)
console.log(params.get('event_id')) // 'evt_9c2f4a1b'
console.log(params.get('product_name')) // 'Standing Desk Pro' ← + avkodat som mellanslag
console.log(params.get('filter')) // 'price:[200+TO+800]' ← %3A och %5B avkodade
console.log(params.getAll('tag')) // ['ergonomic', 'adjustable']
console.log(params.get('redirect')) // 'https://dashboard.internal/orders?view=pending'
// Iterera över alla parametrar
for (const [key, value] of params) {
console.log(`${key}: ${value}`)
}
// event_id: evt_9c2f4a1b
// product_name: Standing Desk Pro
// filter: price:[200+TO+800]
// tag: ergonomic
// tag: adjustable
// redirect: https://dashboard.internal/orders?view=pendingAnalysera frågeparametrar från webbläsarens nuvarande URL
// Nuvarande URL: https://app.example.com/search
// ?q=standing+desk
// &category=office+furniture
// &sort=price_asc
// &page=2
interface SearchFilters {
query: string | null
category: string | null
sort: string
page: number
}
function getSearchFilters(): SearchFilters {
const params = new URLSearchParams(window.location.search)
return {
query: params.get('q'), // 'standing desk'
category: params.get('category'), // 'office furniture'
sort: params.get('sort') ?? 'relevance',
page: Number(params.get('page') ?? '1'),
}
}
const filters = getSearchFilters()
console.log(filters.query) // standing desk (+ avkodat automatiskt)
console.log(filters.category) // office furnitureAvkoda URL-kodad data från filer och API-svar
Två scenarier dyker ständigt upp i riktiga projekt: bearbetning av en fil på disk som innehåller procentkodad data (åtkomstloggar, dataexporter, webhook-inspelningsfiler), och tolkning av URL:en för en inkommande HTTP-förfrågan i en Node.js-server. Båda följer samma princip — använd URL-konstruktorn eller URLSearchParams istället för manuell strängdelning — men detaljerna skiljer sig.
Läsa och avkoda URL-kodade poster från en fil
import { createReadStream } from 'fs'
import { createInterface } from 'readline'
// Fil: orders-export.txt — en URL-kodad post per rad
// customer_name=Erik+Svensson&order_id=ord_9c2f4a&product=Standing+Desk+Pro&total=149.99%20EUR
// customer_name=Anna+Lindqvist&order_id=ord_7b3a1c&product=Ergonomic+Chair&total=89.00%20EUR
// customer_name=Erik+Svensson&order_id=ord_2e8d5f&product=Monitor+Arm&total=59.00%20EUR
interface Order {
customerName: string | null
orderId: string | null
product: string | null
total: string | null
}
async function parseOrdersFile(filePath: string): Promise<Order[]> {
const fileStream = createReadStream(filePath, { encoding: 'utf-8' })
const rl = createInterface({ input: fileStream, crlfDelay: Infinity })
const orders: Order[] = []
for await (const line of rl) {
if (!line.trim()) continue
// URLSearchParams avkodar + som mellanslag och %XX-sekvenser automatiskt
const params = new URLSearchParams(line)
orders.push({
customerName: params.get('customer_name'), // 'Erik Svensson'
orderId: params.get('order_id'), // 'ord_9c2f4a'
product: params.get('product'), // 'Standing Desk Pro'
total: params.get('total'), // '149.99 EUR'
})
}
return orders
}
const orders = await parseOrdersFile('./orders-export.txt')
console.log(orders[0])
// { customerName: 'Erik Svensson', orderId: 'ord_9c2f4a', product: 'Standing Desk Pro', total: '149.99 EUR' }Analysera en Nginx-åtkomstlogg för att avkoda sökfrågor
import { createReadStream } from 'fs'
import { createInterface } from 'readline'
// Nginx-åtkomstloggrader ser ut så här:
// 192.168.1.42 - - [11/Mar/2026:10:23:01 +0000] "GET /api/search?q=standing%20desk%26brand%3ANorthwood&sort=price_asc HTTP/1.1" 200 1842
async function extractSearchQueries(logFile: string): Promise<string[]> {
const rl = createInterface({ input: createReadStream(logFile), crlfDelay: Infinity })
const queries: string[] = []
for await (const line of rl) {
// Extrahera förfrågningssökvägen från loggraden
const match = line.match(/"GET ([^ ]+) HTTP/)
if (!match) continue
try {
const requestUrl = new URL(match[1], 'http://localhost')
const query = requestUrl.searchParams.get('q')
if (query) queries.push(query) // URLSearchParams avkodar automatiskt
} catch {
// Hoppa över felaktiga rader — åtkomstloggar kan innehålla avklippta poster
}
}
return queries
}
const queries = await extractSearchQueries('/var/log/nginx/access.log')
console.log(queries)
// ['standing desk&brand:Northwood', 'ergonomic chair', 'monitor arm 27 inch']Analysera frågeparametrar i en Node.js HTTP-server
import http from 'http'
// Inkommande URL: /api/products?q=standing+desk&warehouse=eu%2Dwest%2D1&minStock=10&cursor=eyJpZCI6MTIzfQ%3D%3D
const server = http.createServer((req, res) => {
// Konstruera en fullständig URL — det andra argumentet är basen som URL-konstruktorn kräver
const requestUrl = new URL(req.url!, 'http://localhost')
const searchQuery = requestUrl.searchParams.get('q') // 'standing desk'
const warehouseId = requestUrl.searchParams.get('warehouse') // 'eu-west-1'
const minStock = Number(requestUrl.searchParams.get('minStock') ?? '0')
const cursor = requestUrl.searchParams.get('cursor') // 'eyJpZCI6MTIzfQ=='
if (!warehouseId) {
res.writeHead(400, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ error: 'warehouse parameter is required' }))
return
}
const cursorData = cursor ? JSON.parse(Buffer.from(cursor, 'base64').toString()) : null
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ searchQuery, warehouseId, minStock, cursorData }))
})
server.listen(3000)När du behöver inspektera en kodad URL under utveckling — för att förstå vad en webhook skickar innan du skriver tolkningskoden — klistra in den direkt i ToolDecks URL Decoder för att omedelbart se den avkodade formen utan att köra ett skript.
URL-avkodning från kommandoraden
För skalskript, CI-pipelines eller snabb engångsgranskning av kodade strängar fungerar flera metoder utan att skriva ett fullständigt skript. Node.js-oneliners är plattformsoberoende; på macOS och Linux är python3 också alltid tillgängligt.
# ── Node.js one-liners ──────────────────────────────────────────────────
# Avkoda ett enstaka procentkodat värde
node -e "console.log(decodeURIComponent(process.argv[1]))" "S%C3%A3o%20Paulo%20%26%20Rio"
# São Paulo & Rio
# Analysera en frågesträng och skriv ut varje nyckel=värde-par (avkodat)
node -e "
const params = new URLSearchParams(process.argv[1])
for (const [k, v] of params) console.log(`${k} = ${v}`)
" "q=standing+desk&warehouse=eu%2Dwest%2D1&minStock=10"
# q = standing desk
# warehouse = eu-west-1
# minStock = 10
# Avkoda och snygg-skriv en URL-kodad JSON-kropp (vanligt vid webhook-felsökning)
node -e "
const raw = decodeURIComponent(process.argv[1])
console.log(JSON.stringify(JSON.parse(raw), null, 2))
" '%7B%22event%22%3A%22purchase%22%2C%22amount%22%3A149.99%2C%22currency%22%3A%22EUR%22%7D'
# {
# "event": "purchase",
# "amount": 149.99,
# "currency": "EUR"
# }
# ── Python one-liner (tillgänglig på de flesta macOS/Linux-system) ───────
# unquote_plus avkodar även + som mellanslag — korrekt för formkodad data
python3 -c "
from urllib.parse import unquote_plus
import sys
print(unquote_plus(sys.argv[1]))
" "Standing+Desk+%26+Ergonomic+Chair"
# Standing Desk & Ergonomic Chair
# ── curl — logga och avkoda en omdirigerings-URL från ett svarshuvud ─────────────
curl -sI "https://api.example.com/short/abc123" | grep -i location | node -e "
const line = require('fs').readFileSync('/dev/stdin', 'utf8')
const url = line.replace(/^location:s*/i, '').trim()
console.log(decodeURIComponent(url))
"Tolerant avkodning med decode-uri-component
Den inbyggda decodeURIComponent() kastar ett URIError vid varje felaktig sekvens — inklusive ett avslutande % utan två efterföljande hexsiffror. I produktionskod som bearbetar användaruppgivna eller tredjeparts-URL:er — loggfrågor, klicknings-URL:er från e-postkampanjer, skrapad webbdata — är felaktiga sekvenser vanliga nog att orsaka krascher. Paketet decode-uri-component (~30 miljoner veckliga npm-nedladdningar) hanterar felaktiga sekvenser tolerant genom att returnera den ursprungliga sekvensen oförändrad istället för att kasta.
npm install decode-uri-component # eller pnpm add decode-uri-component
import decodeUriComponent from 'decode-uri-component'
// Inbyggd funktion kastar vid felaktig indata — kan krascha en förfrågningshanterare
try {
decodeURIComponent('product%name%') // ❌ URIError: URI malformed
} catch (e) {
console.error('Inbyggd kastade:', (e as Error).message)
}
// decode-uri-component returnerar den råa sekvensen istället för att kasta
console.log(decodeUriComponent('product%name%'))
// product%name% ← felaktiga sekvenser lämnade som de är, inget kast
// Giltiga sekvenser avkodas korrekt
console.log(decodeUriComponent('S%C3%A3o%20Paulo%20%26%20Rio'))
// São Paulo & Rio
// Blandat: giltiga sekvenser avkodade, ogiltiga bevarade
console.log(decodeUriComponent('Stockholm%20Office%20%ZZ%20HQ'))
// Stockholm Office %ZZ HQ ← %ZZ är inte giltigt hex — lämnat som det är
// Praktisk användning i en loggbearbetningspipeline
const rawSearchQueries = [
'standing%20desk%20ergonomic',
'price%3A%5B200+TO+800%5D',
'50%25+off', // ← skulle kasta med decodeURIComponent (ensamt %)
'wireless%20keyboard%20%26%20mouse',
]
const decoded = rawSearchQueries.map(q => decodeUriComponent(q))
console.log(decoded)
// ['standing desk ergonomic', 'price:[200+TO+800]', '50%25+off', 'wireless keyboard & mouse']Använd decodeURIComponent() med ett try/catch för applikationskod där du vill veta omedelbart när oväntad indata anländer. Använd decode-uri-component i datapipelines, loggprocessorer och webhook-hanterare där du vill fortsätta bearbetningen även när vissa indata innehåller ogiltig kodning.
Hantera felaktigt procentkodade strängar
Ett ensamt %, en ofullständig sekvens som %A, eller ett ogiltigt par som %GH gör alla att decodeURIComponent() kastar URIError: URI malformed. All användarkontrollerad indata — sökfrågor, URL-fragment, formulärfält som innehåller URL:er, parametrar från e-postkampanjlänkar — kan innehålla dessa sekvenser. Ett säkert omslagsmönster är viktigt för all externt exponerad kod.
Säkra avkodningsomslagsmönster för vanliga scenarier
// ── 1. Grundläggande säker avkodning — returnerar originalsträngen vid fel ──────────
function safeDecode(encoded: string): string {
try {
return decodeURIComponent(encoded)
} catch {
return encoded // returnera rådata vid avkodningsfel — krascha aldrig
}
}
// ── 2. Säker avkodning + behandla + som mellanslag (för formkodade värden) ─────────
function safeFormDecode(formEncoded: string): string {
try {
return decodeURIComponent(formEncoded.replace(/+/g, ' '))
} catch {
return formEncoded.replace(/+/g, ' ') // ersätt åtminstone + även om resten misslyckas
}
}
// ── 3. Säker fullständig frågesträngsparser → vanligt objekt ─────────────────────
function parseQueryString(queryString: string): Record<string, string> {
const result: Record<string, string> = {}
try {
const params = new URLSearchParams(queryString)
for (const [key, value] of params) {
result[key] = value // URLSearchParams hanterar all avkodning internt
}
} catch {
// Returnera tyst tomt vid helt felaktig indata
}
return result
}
// Användning
console.log(safeDecode('S%C3%A3o%20Paulo')) // São Paulo
console.log(safeDecode('search%20for%2050%25+off')) // search for 50% off (ensamt %)
// → faktiskt okej; % här är %25
console.log(safeDecode('malformed%string%')) // malformed%string% (inget kast)
console.log(safeFormDecode('standing+desk+pro')) // standing desk pro
console.log(parseQueryString('q=hello+world&tag=node%20js&page=2'))
// { q: 'hello world', tag: 'node js', page: '2' }Vanliga misstag
Jag har sett dessa fyra mönster orsaka tyst datakorruption eller oväntade krascher i produktion — vanligtvis bara när ett värde råkar innehålla ett specialtecken, vilket innebär att de glider igenom enhetstester och dyker upp med riktiga användardata.
Misstag 1 — Dubbelavkoda ett URLSearchParams-värde
Problem: URLSearchParams.get() returnerar en redan avkodad sträng. Att anropa decodeURIComponent() på den avkodar värdet dubbelt — omvandlar kvarvarande %-tecken i den avkodade utdatan till %25, vilket korrumperar data. Lösning: använd värdet från URLSearchParams.get() direkt — ingen ytterligare avkodning behövs.
// ❌ URLSearchParams har redan avkodat — avkodning igen korrumperar värden med %
const qs = new URLSearchParams('rate=50%25&redirect=https%3A%2F%2Fdashboard.internal%2F')
const rawRate = qs.get('rate') // '50%' ← redan avkodat
const wrongRate = decodeURIComponent(rawRate)
// '50%25' ← % avkodades till %25 på andra passet — nu fel igen// ✅ Använd URLSearchParams.get() direkt — avkodning är automatisk
const qs = new URLSearchParams('rate=50%25&redirect=https%3A%2F%2Fdashboard.internal%2F')
const rate = qs.get('rate') // '50%' ← korrekt, inget extra steg behövs
const redirect = qs.get('redirect') // 'https://dashboard.internal/'
const parsed = new URL(redirect!) // Säkert att konstruera — redan avkodat
console.log(parsed.hostname) // dashboard.internalMisstag 2 — Inte avkoda + som mellanslag för formkodad data
Problem: Formulärsinlämningar och vissa OAuth-bibliotek kodar mellanslag som + (application/x-www-form-urlencoded). Att anropa decodeURIComponent() på dessa data lämnar + som ett bokstavligt plustecken. Lösning: använd URLSearchParams för att tolka formkodad data, eller ersätt + med ett mellanslag innan du anropar decodeURIComponent().
// ❌ decodeURIComponent behandlar + som ett bokstavligt plustecken, inte mellanslag
// OAuth-tokenslutpunkt skickar: grant_type=authorization_code&code=SplxlOBeZQQYb...
// &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
// Vissa äldre OAuth-implementationer använder också + för mellanslag i koder
const formBody = 'customer_name=Erik+Svensson&product=Standing+Desk+Pro&qty=2'
const [, rawVal] = formBody.split('&')[0].split('=')
const name = decodeURIComponent(rawVal)
console.log(name) // 'Erik+Svensson' ← + inte konverterat till mellanslag// ✅ Använd URLSearchParams — följer application/x-www-form-urlencoded-spec
const formBody = 'customer_name=Erik+Svensson&product=Standing+Desk+Pro&qty=2'
const params = new URLSearchParams(formBody)
console.log(params.get('customer_name')) // 'Erik Svensson' ← + korrekt avkodat som mellanslag
console.log(params.get('product')) // 'Standing Desk Pro'Misstag 3 — Använda decodeURI() för enskilda frågeparametervärden
Problem: decodeURI() avkodar inte %26 (&), %3D (=) eller %3F (?) — tecken som vanligtvis kodas inuti parametervärden. Att använda det för att avkoda ett enstaka värde lämnar dessa sekvenser intakta och producerar tyst felaktig utdata. Lösning: använd decodeURIComponent() för enskilda värden; reservera decodeURI() för fullständiga URL-strängar.
// ❌ decodeURI avkodar inte & och = — värdet förblir trasigt const encodedFilter = 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' const filter = decodeURI(encodedFilter) console.log(filter) // 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' ← %3D och %26 inte avkodade
// ✅ decodeURIComponent avkodar alla sekvenser inklusive & och = const encodedFilter = 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' const filter = decodeURIComponent(encodedFilter) console.log(filter) // 'status=active&tier=premium®ion=eu-west' ← korrekt avkodat
Misstag 4 — Inte omsluta decodeURIComponent i try/catch för användarindata
Problem: Ett ensamt %utan två hexsiffror — vanligt i sökfrågor skrivna av användare (“50% rabatt”, “100% bomull”) — gör att decodeURIComponent() kastar URIError: URI malformed och kraschar förfrågningshanteraren om det inte fångas. Lösning: omslut alltid i try/catch när indata härstammar från användardata, URL-fragment eller externa system.
// ❌ Användaren skrev '100% bomull' i en sökruta — ensamt % kraschar servern
// GET /api/search?q=100%25+bomull ← Det här specifika fallet är okej (%25 = %)
// GET /api/search?q=100%+bomull ← Det här kraschar (% inte följt av 2 hexsiffror)
app.get('/api/search', (req, res) => {
const query = decodeURIComponent(req.query.q as string)
// ↑ kastar URIError: URI malformed för '100% bomull' → ohanterat 500-fel
})// ✅ Omslut med try/catch — fall tillbaka till rådata om avkodning misslyckas
app.get('/api/search', (req, res) => {
let query: string
try {
query = decodeURIComponent(req.query.q as string)
} catch {
query = req.query.q as string // använd råvärdet istället för att krascha
}
// fortsätt bearbeta säkert — query är antingen avkodat eller rått
})decodeURIComponent vs decodeURI vs URLSearchParams — Snabb jämförelse
| Metod | Avkodar %XX | Avkodar + som mellanslag | Kastar vid felaktig indata | Avkodar & = ? # | Användningsfall | Kräver installation |
|---|---|---|---|---|---|---|
| decodeURIComponent() | ✅ alla | ❌ nej | ✅ URIError | ✅ ja | Enskilda värden och sökvägssegment | Nej |
| decodeURI() | ✅ de flesta | ❌ nej | ✅ URIError | ❌ nej | Fullständiga URL-strängar | Nej |
| URLSearchParams | ✅ alla | ✅ ja | ❌ tyst | ✅ ja | Frågesträngsanalys med automatisk avkodning | Nej |
| URL-konstruktorn | ✅ alla | ✅ ja | ✅ TypeError | ✅ ja | Fullständig URL-analys och normalisering | Nej |
| decode-uri-component | ✅ alla | ❌ nej | ❌ tyst | ✅ ja | Batchavkodning med tolerans för felaktig indata | npm install |
| querystring.unescape() | ✅ alla | ❌ nej | ❌ tyst | ✅ ja | Äldre Node.js (utfasad sedan v16) | Nej (inbyggd) |
I de allra flesta fall reduceras valet till tre scenarier. Använd URLSearchParams för att analysera frågesträngar — det hanterar avkodning, regeln om +-som-mellanslag och upprepade nycklar automatiskt. Använd decodeURIComponent() (omsluten i try/catch) för ett enstaka värde eller sökvägssegment, särskilt när du förväntar dig %2F-kodade snedstreck inuti ett segment. Använd decodeURI() bara när du har en fullständig URL-sträng med icke-ASCII-tecken i sökvägen och de strukturella tecknen (/ ? & =) måste förbli kodade i utdatan.
Vanliga frågor
Relaterade verktyg
För ettklicksavkodning utan att skriva kod, klistra in din procentkodade sträng direkt i ToolDecks URL Decoder — det avkodar direkt i webbläsaren, med resultatet redo att kopiera till din kod eller terminal.
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.
Marcus specialises in JavaScript performance, build tooling, and the inner workings of the V8 engine. He has spent years profiling and optimising React applications, working on bundler configurations, and squeezing every millisecond out of critical rendering paths. He writes about Core Web Vitals, JavaScript memory management, and the tools developers reach for when performance really matters.