URL Decode JavaScript — decodeURIComponent()

·Front-end & Node.js Developer·Granskad avMarcus Webb·Publicerad

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.

Before · text
After · text
// 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

JavaScript (browser / Node.js)
// 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

JavaScript
// 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'))    // platform

Avkoda icke-ASCII- och Unicode-sökvägssegment

JavaScript
// 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)
Obs: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:

KodatTeckendecodeURIComponent()decodeURI()URLSearchParams
%20mellanslagmellanslag ✅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

JavaScript
// 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
Obs:Föredra 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

JavaScript (browser / Node.js 10+)
// 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=pending

Analysera frågeparametrar från webbläsarens nuvarande URL

JavaScript (browser)
// 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 furniture

Avkoda 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

JavaScript (Node.js 10+)
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

JavaScript (Node.js)
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

JavaScript (Node.js 10+)
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.

bash
# ── 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.

bash
npm install decode-uri-component
# eller
pnpm add decode-uri-component
JavaScript (Node.js)
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

JavaScript
// ── 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.

Before · JavaScript
After · JavaScript
// ❌ 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.internal

Misstag 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().

Before · JavaScript
After · JavaScript
// ❌ 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.

Before · JavaScript
After · JavaScript
// ❌ 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&region=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.

Before · JavaScript
After · JavaScript
// ❌ 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

MetodAvkodar %XXAvkodar + som mellanslagKastar vid felaktig indataAvkodar & = ? #AnvändningsfallKräver installation
decodeURIComponent()✅ alla❌ nej✅ URIError✅ jaEnskilda värden och sökvägssegmentNej
decodeURI()✅ de flesta❌ nej✅ URIError❌ nejFullständiga URL-strängarNej
URLSearchParams✅ alla✅ ja❌ tyst✅ jaFrågesträngsanalys med automatisk avkodningNej
URL-konstruktorn✅ alla✅ ja✅ TypeError✅ jaFullständig URL-analys och normaliseringNej
decode-uri-component✅ alla❌ nej❌ tyst✅ jaBatchavkodning med tolerans för felaktig indatanpm 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

Vad är skillnaden mellan decodeURIComponent() och decodeURI() i JavaScript?
decodeURIComponent() avkodar varje procentkodad sekvens i strängen, inklusive tecken med strukturell betydelse i en URL — & (%26), = (%3D), ? (%3F), # (%23), / (%2F) och : (%3A). Den är utformad för att avkoda enskilda frågeparametervärden eller sökvägssegment. decodeURI() bevarar dessa strukturella tecken — den avkodar inte %26, %3D, %3F, %23, %2F eller %3A — eftersom den är utformad för att sanera en komplett URL utan att förstöra dess frågesträngsstruktur. Att använda decodeURI() på ett enskilt parametervärde som innehåller ett kodat & eller = lämnar tyst dessa sekvenser oavkodade och producerar felaktig utdata.
Varför kastar decodeURIComponent() ett URIError för vissa strängar?
decodeURIComponent() kastar URIError: URI malformed när indata innehåller ett % som inte följs av exakt två giltiga hexadecimala siffror. Vanliga utlösare: ett ensamt % i slutet av en sträng ("50% rabatt" skrivet av en användare), en ofullständig sekvens ("%A"), eller ett ogiltigt hexpar ("%GH"). Detta händer oftast med sökfrågor skrivna av användare eller värden inklistrade från text som aldrig var avsedd att vara URL-kodad. Lösningen är att omsluta decodeURIComponent() i ett try/catch-block och returnera råsträngen vid fel. npm-paketet decode-uri-component erbjuder samma lösning utan att kräva en try/catch-omslutning.
Avkodar URLSearchParams procentkodade värden automatiskt?
Ja. Varje värde som returneras av URLSearchParams.get() och URLSearchParams.getAll() är fullständigt avkodat — du ska aldrig anropa decodeURIComponent() på deras utdata. URLSearchParams följer också specifikationen application/x-www-form-urlencoded, som avkodar + som ett mellanslag, vilket gör det korrekt för HTML-formulärsinlämningar och OAuth-tokensvar. Det enda fallet där URLSearchParams inte kan hjälpa är avkodning av ett fristående kodat värde som inte är en del av en frågesträng — för det, använd decodeURIComponent() med en try/catch.
Hur avkodar jag +-tecknet som mellanslag i JavaScript?
decodeURIComponent() behandlar + som ett bokstavligt plustecken — det konverterar inte + till ett mellanslag. Detta är avsiktligt: + som mellanslag är en application/x-www-form-urlencoded-konvention, separerad från procentkodningsstandarden. För att avkoda + som mellanslag, använd URLSearchParams (som följer formkodningsspecen), eller ersätt + innan du anropar decodeURIComponent(): decodeURIComponent(str.replace(/\+/g, ' ')). Notera att ersätta + med %20 innan avkodning också fungerar men är lite mer utförligt. Föredra alltid URLSearchParams för att analysera fullständiga frågesträngar — det hanterar både %20 och + korrekt.
Hur avkodar jag en URL-sträng i Node.js?
Använd samma globala funktioner som finns tillgängliga i alla webbläsare — ingen import behövs i Node.js 10+. decodeURIComponent() för enskilda värden, decodeURI() för fullständiga URL-strängar, URLSearchParams för frågesträngar. För inkommande HTTP-förfrågnings-URL:er, använd new URL(req.url, 'http://localhost') — URL-konstruktorn normaliserar URL:en och exponerar .searchParams (automatiskt avkodat) och .pathname (avkodat på URL-nivå). Den äldre querystring.unescape()-funktionen finns fortfarande men är utfasad sedan Node.js 16 — föredra decodeURIComponent() istället.
Hur tolkar jag en URL-frågesträng till ett objekt i JavaScript?
Använd URLSearchParams med Object.fromEntries(): const params = Object.fromEntries(new URLSearchParams(queryString)). Det ger ett vanligt objekt med alla parameternycklar och avkodade värden. Notera att Object.fromEntries() vid duplicerade nycklar bara behåller det sista värdet — för upprepade nycklar som tag=one&tag=two, använd URLSearchParams.getAll('tag') istället. För webbläsaren analyserar new URLSearchParams(window.location.search) automatiskt den aktuella sidans frågesträng. För Node.js, analysera från new URL(req.url, base).searchParams.

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.

AC
Alex ChenFront-end & Node.js Developer

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.

MW
Marcus WebbTeknisk granskare

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.