URL Decode JavaScript — decodeURIComponent()
Nutze das kostenlose URL Decode Online direkt im Browser – keine Installation erforderlich.
URL Decode Online online testen →Prozent-kodierte Zeichenketten tauchen in JavaScript-Code ständig auf — eine Suchanfrage kommt an als q=standing+desk%26price%3A200, eine OAuth- Weiterleitung als next=https%3A%2F%2Fdashboard.internal%2F, ein Speicherpfad als reports%2F2025%2Fq1.pdf. Die URL-Dekodierung in JavaScript läuft auf die Wahl der richtigen von drei eingebauten Funktionen hinaus: decodeURIComponent(), decodeURI() und URLSearchParams — und die Wahl zwischen ihnen ist die Hauptursache der meisten stillen Datenkorrumptionen, die ich in Produktionscode-Bases gesehen habe, insbesondere der +-als-Leerzeichen-Sonderfall und die doppelte Dekodierung. Für eine schnelle Einzel-Dekodierung ohne Code erledigt der URL Decoder von ToolDeck das sofort im Browser. Dieses JavaScript-URL-Dekodierungs-Tutorial behandelt alle drei Funktionen ausführlich (ES2015+ / Node.js 10+): wann welche zu verwenden ist, wie sie sich bei Leerzeichen und reservierten Zeichen unterscheiden, Dekodierung aus Dateien und HTTP-Anfragen, sicheres Fehlerhandling und die vier Fehler, die die meisten subtilen Produktionsprobleme verursachen.
- ✓decodeURIComponent() dekodiert alle prozent-kodierten Sequenzen — es ist die richtige Wahl für einzelne Query-Parameter-Werte und Pfadsegmente
- ✓decodeURI() bewahrt strukturelle URI-Zeichen wie / ? & = # : — verwende es nur beim Dekodieren einer vollständigen URL-Zeichenkette, niemals für einzelne Werte
- ✓URLSearchParams.get() gibt bereits dekodierte Werte zurück — decodeURIComponent() darauf aufzurufen verursacht doppelte Dekodierung
- ✓decodeURIComponent() dekodiert + NICHT als Leerzeichen — für form-kodierte Daten (application/x-www-form-urlencoded) verwende URLSearchParams oder ersetze + vor dem Dekodieren
- ✓Umhülle decodeURIComponent() immer mit try/catch, wenn die Eingabe aus Benutzerdaten stammt — ein einzelnes % oder eine unvollständige Sequenz wirft einen URIError
Was ist URL-Dekodierung?
Prozent-Kodierung (formal definiert in RFC 3986) ersetzt Zeichen, die in einer URL unsicher oder strukturell bedeutsam sind, durch ein %-Zeichen gefolgt von zwei Hexadezimalziffern — dem UTF-8-Bytewert des Zeichens. URL-Dekodierung kehrt diese Transformation um: jede %XX-Sequenz wird zurück in ihr ursprüngliches Byte umgewandelt, und die resultierende Bytesequenz wird als UTF-8-Text interpretiert. Ein Leerzeichen dekodiert aus %20, ein Schrägstrich aus %2F, das Nicht-ASCII-Zeichen ü aus %C3%BC (seiner Zwei-Byte-UTF-8-Darstellung).
Die Zeichen, die niemals kodiert werden — sogenannte nicht-reservierte Zeichen — sind Buchstaben A–Z und a–z, Ziffern 0–9 sowie - _ . ~. Alles andere hat entweder eine strukturelle Rolle in der URL (wie / zur Trennung von Pfadsegmenten oder & zur Trennung von Query-Parametern) oder muss kodiert werden, wenn es als Datenwert verwendet wird. Das praktische Ergebnis: Ein Suchfilter wie status=active&tier=premium kodiert als einzelner Query-Parameter-Wert sieht bei Ankunft völlig anders aus als das Original.
// Prozent-kodiert — wie in einer HTTP-Anfrage oder einem Webhook-Payload empfangen "q=price%3A%5B200+TO+800%5D%20AND%20brand%3ANorthwood%20%26%20status%3Ain-stock"
// Nach URL-Dekodierung — der ursprüngliche Elasticsearch-Abfragefilter "q=price:[200 TO 800] AND brand:Northwood & status:in-stock"
decodeURIComponent() — Die Standardfunktion zur Dekodierung von Werten
decodeURIComponent() ist das Arbeitspferd der URL-Dekodierung in JavaScript. Es dekodiert jede %XX-Sequenz in der Eingabezeichenkette — einschließlich Zeichen, die in einer URL eine strukturelle Bedeutung haben, wie %2F (Schrägstrich), %3F (Fragezeichen), %26 (kaufmännisches Und) und %3D (Gleichheitszeichen). Das macht es zur richtigen Wahl für die Dekodierung einzelner Query-Parameter-Werte und Pfadsegmente, aber zur falschen Wahl für die Dekodierung einer vollständigen URL — wo diese strukturellen Zeichen kodiert bleiben müssen. Es ist eine globale Funktion: in keiner JavaScript-Umgebung ist ein Import nötig.
Minimales Funktionsbeispiel
// Einzelne Query-Parameter-Werte dekodieren — der häufige Fall
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]'
// Hinweis: + wird NICHT als Leerzeichen dekodiert — siehe den +-Abschnitt in der Vergleichstabelle
console.log(city) // São Paulo
console.log(district) // Itáim Bibi
console.log(category) // office furniture
console.log(filter) // price:[200+TO+800]Eine aus einem Query-Parameter extrahierte Weiterleitungs-URL dekodieren
// Die Weiterleitungs-URL wurde prozent-kodiert, als sie als Parameterwert eingebettet wurde
// Empfangsseite: extrahieren, dann verwenden — mit URLSearchParams ist keine manuelle Dekodierung nötig
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') // Automatisch dekodiert durch URLSearchParams
const sessionId = url.searchParams.get('session_id') // 'sid_7x9p2k'
// rawNext ist bereits dekodiert: 'https://dashboard.internal/reports?view=weekly&team=platform'
// decodeURIComponent(rawNext) NICHT erneut aufrufen — das wäre doppelte Dekodierung
const nextUrl = new URL(rawNext!)
console.log(nextUrl.hostname) // dashboard.internal
console.log(nextUrl.searchParams.get('view')) // weekly
console.log(nextUrl.searchParams.get('team')) // platformNicht-ASCII- und Unicode-Pfadsegmente dekodieren
// REST-API mit internationalisierten Pfadsegmenten
// Jedes UTF-8-Byte des ursprünglichen Zeichens wurde separat prozent-kodiert
const encodedSegments = [
'%E6%9D%B1%E4%BA%AC', // 東京 (Tokio) — 3 Bytes pro Zeichen
'M%C3%BCnchen', // München — ü als 2 Bytes kodiert
'caf%C3%A9', // café — é als vorkompiniertes NFC
'S%C3%A3o%20Paulo', // São Paulo
]
encodedSegments.forEach(seg => {
console.log(decodeURIComponent(seg))
})
// 東京
// München
// café
// São Paulo
// Einen Datei-Key aus einer Storage-API-URL extrahieren
// Der Objekt-Key enthielt ein /, das als %2F im Pfadsegment kodiert wurde
const storageUrl = 'https://storage.api.example.com/v1/objects/reports%2F2025%2Fq1-financials.pdf'
const rawKey = new URL(storageUrl).pathname.replace('/v1/objects/', '')
// .pathname dekodiert die URL-Ebenen-Kodierung, aber %2F (als %252F auf URL-Ebene) bleibt
// decodeURIComponent für den letzten Schritt verwenden:
const fileKey = decodeURIComponent(rawKey) // 'reports/2025/q1-financials.pdf'
console.log(fileKey)decodeURIComponent() wirft einen URIError, wenn die Eingabe ein % enthält, dem keine zwei gültigen Hexadezimalziffern folgen — zum Beispiel ein einzelnes % am Ende einer Zeichenkette oder eine Sequenz wie %GH. Umhülle es immer mit try/catch, wenn benutzerseitig eingegebene Daten dekodiert werden. Die sicheren Dekodierungsmuster werden im Abschnitt Fehlerbehandlung behandelt.JavaScript-URL-Dekodierungsfunktionen — Zeichenreferenz
Die drei eingebauten Dekodierungsfunktionen unterscheiden sich darin, welche kodierten Sequenzen sie genau dekodieren. Die Tabelle zeigt das Verhalten für die in der Praxis wichtigsten Zeichen:
| Kodiert | Zeichen | decodeURIComponent() | decodeURI() | URLSearchParams |
|---|---|---|---|---|
| %20 | Leerzeichen | Leerzeichen ✅ | Leerzeichen ✅ | Leerzeichen ✅ |
| + | Plus (Form) | + (beibehalten) | + (beibehalten) | Leerzeichen ✅ |
| %2B | + literal | + ✅ | + ✅ | + ✅ |
| %26 | & | & ✅ | & (beib.) ❌ | & ✅ |
| %3D | = | = ✅ | = (beib.) ❌ | = ✅ |
| %3F | ? | ? ✅ | ? (beib.) ❌ | ? ✅ |
| %23 | # | # ✅ | # (beib.) ❌ | # ✅ |
| %2F | / | / ✅ | / (beib.) ❌ | / ✅ |
| %3A | : | : ✅ | : (beib.) ❌ | : ✅ |
| %40 | @ | @ ✅ | @ (beib.) ❌ | @ ✅ |
| %25 | % | % ✅ | % ✅ | % ✅ |
| %C3%BC | ü | ü ✅ | ü ✅ | ü ✅ |
Die zwei kritischen Zeilen sind + und die strukturellen Zeichen (%26, %3D, %3F). URLSearchParams dekodiert + als Leerzeichen, weil es der application/x-www-form-urlencoded-Spezifikation folgt — korrekt für HTML-Formularübermittlungen, aber anders als decodeURIComponent() mit demselben Zeichen. Und decodeURI() überspringt still %26, %3D und %3F — was korrekt aussieht, bis ein Wert tatsächlich ein kodiertes kaufmännisches Und oder Gleichheitszeichen enthält.
decodeURI() — Eine vollständige URL dekodieren ohne ihre Struktur zu zerstören
decodeURI() ist das Gegenstück zu encodeURI(). Es dekodiert eine vollständige URL-Zeichenkette und bewahrt dabei Zeichen, die in einer URI eine strukturelle Bedeutung haben: ; , / ? : @ & = + $ #. Diese bleiben in ihrer prozent-kodierten Form (oder als Literal-Zeichen, wenn sie unkodiert in der Eingabe aufgetaucht sind). Das macht decodeURI() sicher für die Bereinigung vollständiger URLs, die Nicht-ASCII-Zeichen im Pfad oder Hostnamen enthalten können, ohne versehentlich die Query-String-Struktur zu zerstören.
Eine URL mit Nicht-ASCII-Pfadsegmenten bereinigen
// Eine CDN-URL mit internationalisierten Pfadsegmenten und einem strukturierten Query-String // decodeURI() dekodiert nicht-ASCII-Pfade, bewahrt aber ? & = 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 // ↑ Nicht-ASCII dekodiert; ? & = beibehalten — URL bleibt strukturell gültig // decodeURIComponent würde die URL zerstören — : / ? & = werden alle auf einmal dekodiert const broken = decodeURIComponent(encodedUrl) // Sieht hier gleich aus, aber eine URL wie 'https%3A%2F%2F...' würde zerstört
URL-Konstruktor gegenüber decodeURI(), wenn du auch auf einzelne URL-Komponenten zugreifen musst. new URL(str) normalisiert die Eingabe, validiert ihre Struktur und macht .pathname, .searchParams und .hostname als bereits dekodierte Eigenschaften verfügbar. Verwende decodeURI() nur für Fälle, in denen du nur ein Zeichenkettenergebnis benötigst und den URL-Konstruktor nicht verwenden kannst (zum Beispiel in sehr alten Node.js 6-Umgebungen ohne die globale URL-Klasse).URLSearchParams — Automatische Dekodierung für Query-Strings
URLSearchParams ist der idiomatische Weg zum Parsen von Query-Strings in modernem JavaScript. Jeder von .get(), .getAll() oder Iteration zurückgegebene Wert ist automatisch dekodiert — einschließlich + als Leerzeichen für form-kodierte Daten. Es ist global in allen modernen Browsern und Node.js 10+ verfügbar, erfordert keinen Import und behandelt Randfälle, bei denen manuelles String-Splitting versagt.
Einen eingehenden Query-String parsen
// Einen Webhook-Callback- oder OAuth-Weiterleitungs-Query-String parsen
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' ← + als Leerzeichen dekodiert
console.log(params.get('filter')) // 'price:[200+TO+800]' ← %3A und %5B dekodiert
console.log(params.getAll('tag')) // ['ergonomic', 'adjustable']
console.log(params.get('redirect')) // 'https://dashboard.internal/orders?view=pending'
// Alle Parameter iterieren
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=pendingQuery-Parameter aus der aktuellen Browser-URL parsen
// Aktuelle 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 (+ automatisch dekodiert)
console.log(filters.category) // office furnitureURL-kodierte Daten aus Dateien und API-Antworten dekodieren
In realen Projekten tauchen zwei Szenarien ständig auf: das Verarbeiten einer Datei auf dem Datenträger, die prozent-kodierte Daten enthält (Zugriffsprotokolle, Datenexporte, Webhook-Aufnahmedateien), und das Parsen der URL einer eingehenden HTTP-Anfrage in einem Node.js-Server. Beide folgen demselben Prinzip — verwende den URL-Konstruktor oder URLSearchParams statt manuellem String-Splitting — aber die Details unterscheiden sich.
URL-kodierte Datensätze aus einer Datei lesen und dekodieren
import { createReadStream } from 'fs'
import { createInterface } from 'readline'
// Datei: orders-export.txt — ein URL-kodierter Datensatz pro Zeile
// customer_name=Lukas+Bauer&order_id=ord_9c2f4a&product=Standing+Desk+Pro&total=149.99%20EUR
// customer_name=Sophie+M%C3%BCller&order_id=ord_7b3a1c&product=Ergonomic+Chair&total=89.00%20EUR
// customer_name=Lukas+Bauer&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 dekodiert + als Leerzeichen und %XX-Sequenzen automatisch
const params = new URLSearchParams(line)
orders.push({
customerName: params.get('customer_name'), // 'Lukas Bauer'
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: 'Lukas Bauer', orderId: 'ord_9c2f4a', product: 'Standing Desk Pro', total: '149.99 EUR' }Ein Nginx-Zugriffsprotokoll parsen, um Suchanfragen zu dekodieren
import { createReadStream } from 'fs'
import { createInterface } from 'readline'
// Nginx-Zugriffsprotokoll-Zeilen sehen so aus:
// 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) {
// Den Anfragepfad aus der Protokollzeile extrahieren
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 dekodiert automatisch
} catch {
// Fehlerhafte Zeilen überspringen — Zugriffsprotokolle können abgeschnittene Einträge enthalten
}
}
return queries
}
const queries = await extractSearchQueries('/var/log/nginx/access.log')
console.log(queries)
// ['standing desk&brand:Northwood', 'ergonomic chair', 'monitor arm 27 inch']Query-Parameter in einem Node.js-HTTP-Server parsen
import http from 'http'
// Eingehende URL: /api/products?q=standing+desk&warehouse=eu%2Dwest%2D1&minStock=10&cursor=eyJpZCI6MTIzfQ%3D%3D
const server = http.createServer((req, res) => {
// Eine vollständige URL erstellen — das zweite Argument ist die für den URL-Konstruktor erforderliche Basis
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)Wenn du während der Entwicklung eine kodierte URL untersuchen möchtest — um zu verstehen, was ein Webhook sendet, bevor du den Parsing-Code schreibst — füge sie direkt in den URL Decoder von ToolDeck ein, um die dekodierte Form sofort zu sehen, ohne ein Skript auszuführen.
URL-Dekodierung über die Kommandozeile
Für Shell-Skripte, CI-Pipelines oder schnelle Einzel-Prüfung kodierter Zeichenketten stehen mehrere Ansätze ohne vollständiges Skript zur Verfügung. Node.js-Einzeiler sind plattformübergreifend; auf macOS und Linux ist außerdem immer python3 verfügbar.
# ── Node.js-Einzeiler ────────────────────────────────────────────────────
# Einen einzelnen prozent-kodierten Wert dekodieren
node -e "console.log(decodeURIComponent(process.argv[1]))" "S%C3%A3o%20Paulo%20%26%20Rio"
# São Paulo & Rio
# Einen Query-String parsen und jedes Schlüssel=Wert-Paar (dekodiert) ausgeben
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
# Einen URL-kodierten JSON-Body dekodieren und formatiert ausgeben (häufig beim Webhook-Debugging)
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-Einzeiler (auf den meisten macOS/Linux-Systemen verfügbar) ─────
# unquote_plus dekodiert auch + als Leerzeichen — korrekt für form-kodierte Daten
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 — eine Weiterleitungs-URL aus einem Antwort-Header protokollieren und dekodieren ──────────
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))
"Fehlertolerante Dekodierung mit decode-uri-component
Das eingebaute decodeURIComponent() wirft einen URIError bei jeder fehlerhaften Sequenz — einschließlich eines abschließenden % ohne zwei folgende Hex-Ziffern. In Produktionscode, der benutzerseitig eingegebene oder drittpartei-URLs verarbeitet — Suchprotokoll-Abfragen, Klickpfad-URLs aus E-Mail-Kampagnen, gescrapte Webdaten — sind fehlerhafte Sequenzen häufig genug, um Abstürze zu verursachen. Das Paket decode-uri-component (~30 Mio. wöchentliche npm-Downloads) behandelt fehlerhafte Sequenzen fehlertolerantly, indem es die ursprüngliche Sequenz unverändert zurückgibt, anstatt zu werfen.
npm install decode-uri-component # oder pnpm add decode-uri-component
import decodeUriComponent from 'decode-uri-component'
// Native Funktion wirft bei fehlerhafter Eingabe — kann einen Request-Handler zum Absturz bringen
try {
decodeURIComponent('product%name%') // ❌ URIError: URI malformed
} catch (e) {
console.error('Native geworfen:', (e as Error).message)
}
// decode-uri-component gibt die rohe Sequenz zurück statt zu werfen
console.log(decodeUriComponent('product%name%'))
// product%name% ← fehlerhafte Sequenzen bleiben unverändert, kein Wurf
// Gültige Sequenzen werden korrekt dekodiert
console.log(decodeUriComponent('S%C3%A3o%20Paulo%20%26%20Rio'))
// São Paulo & Rio
// Gemischt: gültige Sequenzen dekodiert, ungültige beibehalten
console.log(decodeUriComponent('Berlin%20Office%20%ZZ%20HQ'))
// Berlin Office %ZZ HQ ← %ZZ ist kein gültiges Hex — bleibt unverändert
// Praktische Verwendung in einer Protokollverarbeitungs-Pipeline
const rawSearchQueries = [
'standing%20desk%20ergonomic',
'price%3A%5B200+TO+800%5D',
'50%25+off', // ← würde mit decodeURIComponent werfen (einzelnes %)
'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']Verwende decodeURIComponent() mit einem try/catch für Anwendungscode, bei dem du sofort wissen möchtest, wenn unerwartete Eingaben ankommen. Greife auf decode-uri-component in Datenpipelines, Protokollprozessoren und Webhook-Handlern zurück, wo du die Verarbeitung auch dann fortsetzen möchtest, wenn einige Eingaben eine ungültige Kodierung enthalten.
Fehlerhafte Prozent-kodierte Zeichenketten behandeln
Ein einzelnes %, eine unvollständige Sequenz wie %A oder ein ungültiges Paar wie %GH führen alle dazu, dass decodeURIComponent() URIError: URI malformed wirft. Jede benutzerkontrollierte Eingabe — Suchanfragen, URL-Fragmente, Formularfelder mit URLs, Parameter aus E-Mail-Kampagnen-Links — kann diese Sequenzen enthalten. Ein sicherer Wrapper ist für jeden extern ausgerichteten Code unerlässlich.
Sichere Dekodierungs-Wrapper für häufige Szenarien
// ── 1. Grundlegende sichere Dekodierung — gibt bei Fehler die ursprüngliche Zeichenkette zurück ──
function safeDecode(encoded: string): string {
try {
return decodeURIComponent(encoded)
} catch {
return encoded // Roheingabe zurückgeben, wenn Dekodierung fehlschlägt — niemals abstürzen
}
}
// ── 2. Sichere Dekodierung + + als Leerzeichen behandeln (für form-kodierte Werte) ─────────
function safeFormDecode(formEncoded: string): string {
try {
return decodeURIComponent(formEncoded.replace(/+/g, ' '))
} catch {
return formEncoded.replace(/+/g, ' ') // zumindest + ersetzen, auch wenn der Rest fehlschlägt
}
}
// ── 3. Sicherer vollständiger Query-String-Parser → einfaches 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 kümmert sich intern um die gesamte Dekodierung
}
} catch {
// Bei vollständig fehlerhafter Eingabe leer zurückgeben
}
return result
}
// Verwendung
console.log(safeDecode('S%C3%A3o%20Paulo')) // São Paulo
console.log(safeDecode('search%20for%2050%25+off')) // search for 50% off (einzelnes %)
// → tatsächlich okay; % hier ist %25
console.log(safeDecode('malformed%string%')) // malformed%string% (kein Wurf)
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' }Häufige Fehler
Diese vier Muster verursachen stille Datenkorrumption oder unerwartete Abstürze in der Produktion — meistens nur, wenn ein Wert zufällig ein Sonderzeichen enthält, was bedeutet, dass sie durch Unit-Tests schlüpfen und erst mit echten Benutzerdaten auftauchen.
Fehler 1 — Einen URLSearchParams-Wert doppelt dekodieren
Problem: URLSearchParams.get() gibt eine bereits dekodierte Zeichenkette zurück. Das Aufrufen von decodeURIComponent() darauf dekodiert den Wert doppelt — wandelt verbleibende %-Zeichen in der dekodierten Ausgabe in %25 um und korrumpiert die Daten. Lösung: den Wert von URLSearchParams.get() direkt verwenden — keine weitere Dekodierung ist nötig.
// ❌ URLSearchParams hat bereits dekodiert — erneutes Dekodieren korrumpiert Werte mit %
const qs = new URLSearchParams('rate=50%25&redirect=https%3A%2F%2Fdashboard.internal%2F')
const rawRate = qs.get('rate') // '50%' ← bereits dekodiert
const wrongRate = decodeURIComponent(rawRate)
// '50%25' ← % wurde im zweiten Durchgang zu %25 dekodiert — jetzt wieder falsch// ✅ URLSearchParams.get() direkt verwenden — Dekodierung ist automatisch
const qs = new URLSearchParams('rate=50%25&redirect=https%3A%2F%2Fdashboard.internal%2F')
const rate = qs.get('rate') // '50%' ← korrekt, kein weiterer Schritt nötig
const redirect = qs.get('redirect') // 'https://dashboard.internal/'
const parsed = new URL(redirect!) // Sicher zu konstruieren — bereits dekodiert
console.log(parsed.hostname) // dashboard.internalFehler 2 — + bei form-kodierten Daten nicht als Leerzeichen dekodieren
Problem: Formularübermittlungen und einige OAuth-Bibliotheken kodieren Leerzeichen als + (application/x-www-form-urlencoded). Das Aufrufen von decodeURIComponent() auf diesen Daten lässt + als wörtliches Plus-Zeichen. Lösung: URLSearchParams zum Parsen form-kodierter Daten verwenden, oder + vor dem Aufruf von decodeURIComponent() durch ein Leerzeichen ersetzen.
// ❌ decodeURIComponent behandelt + als wörtliches Plus, nicht als Leerzeichen
// OAuth-Token-Endpunkt sendet: grant_type=authorization_code&code=SplxlOBeZQQYb...
// &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
// Einige Legacy-OAuth-Implementierungen verwenden auch + für Leerzeichen in Codes
const formBody = 'customer_name=Lukas+Bauer&product=Standing+Desk+Pro&qty=2'
const [, rawVal] = formBody.split('&')[0].split('=')
const name = decodeURIComponent(rawVal)
console.log(name) // 'Lukas+Bauer' ← + nicht zu Leerzeichen umgewandelt// ✅ URLSearchParams verwenden — folgt der application/x-www-form-urlencoded-Spezifikation
const formBody = 'customer_name=Lukas+Bauer&product=Standing+Desk+Pro&qty=2'
const params = new URLSearchParams(formBody)
console.log(params.get('customer_name')) // 'Lukas Bauer' ← + korrekt als Leerzeichen dekodiert
console.log(params.get('product')) // 'Standing Desk Pro'Fehler 3 — decodeURI() für einzelne Query-Parameter-Werte verwenden
Problem: decodeURI() dekodiert %26 (&), %3D (=) oder %3F (?) nicht — Zeichen, die häufig in Parameterwerten kodiert sind. Es zur Dekodierung eines einzelnen Werts zu verwenden lässt diese Sequenzen intakt und produziert still ein falsches Ergebnis. Lösung: decodeURIComponent() für einzelne Werte verwenden; decodeURI() für vollständige URL-Zeichenketten reservieren.
// ❌ decodeURI dekodiert & und = nicht — der Wert bleibt fehlerhaft const encodedFilter = 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' const filter = decodeURI(encodedFilter) console.log(filter) // 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' ← %3D und %26 nicht dekodiert
// ✅ decodeURIComponent dekodiert alle Sequenzen einschließlich & und = const encodedFilter = 'status%3Dactive%26tier%3Dpremium%26region%3Deu-west' const filter = decodeURIComponent(encodedFilter) console.log(filter) // 'status=active&tier=premium®ion=eu-west' ← korrekt dekodiert
Fehler 4 — decodeURIComponent bei Benutzereingaben nicht in try/catch einschließen
Problem: Ein einzelnes %ohne zwei folgende Hex-Ziffern — häufig in von Benutzern getippten Suchanfragen (“50% Rabatt”, “100% Baumwolle”) — führt dazu, dass decodeURIComponent() URIError: URI malformed wirft, was den Request-Handler zum Absturz bringt, wenn es unbehandelt bleibt. Lösung: immer in try/catch einschließen, wenn die Eingabe aus Benutzerdaten, URL-Fragmenten oder externen Systemen stammt.
// ❌ Benutzer tippte '100% Baumwolle' in ein Suchfeld — einzelnes % bringt Server zum Absturz
// GET /api/search?q=100%25+Baumwolle ← Dieser spezifische Fall ist okay (%25 = %)
// GET /api/search?q=100%+Baumwolle ← Das bringt zum Absturz (% nicht von 2 Hex-Ziffern gefolgt)
app.get('/api/search', (req, res) => {
const query = decodeURIComponent(req.query.q as string)
// ↑ wirft URIError: URI malformed für '100% Baumwolle' → unbehandelter 500-Fehler
})// ✅ In try/catch einschließen — bei Dekodierungsfehler auf Roheingabe zurückfallen
app.get('/api/search', (req, res) => {
let query: string
try {
query = decodeURIComponent(req.query.q as string)
} catch {
query = req.query.q as string // Rohen Wert verwenden statt abzustürzen
}
// Sicher mit der Verarbeitung fortfahren — query ist entweder dekodiert oder roh
})decodeURIComponent vs decodeURI vs URLSearchParams — Kurzübersicht
| Methode | Dekodiert %XX | Dekodiert + als Leerzeichen | Wirft bei fehlerhafter Eingabe | Dekodiert & = ? # | Anwendungsfall | Installation erforderlich |
|---|---|---|---|---|---|---|
| decodeURIComponent() | ✅ alle | ❌ nein | ✅ URIError | ✅ ja | Einzelne Werte und Pfadsegmente | Nein |
| decodeURI() | ✅ die meisten | ❌ nein | ✅ URIError | ❌ nein | Vollständige URL-Zeichenketten | Nein |
| URLSearchParams | ✅ alle | ✅ ja | ❌ still | ✅ ja | Query-String-Parsing mit automatischer Dekodierung | Nein |
| URL-Konstruktor | ✅ alle | ✅ ja | ✅ TypeError | ✅ ja | Vollständiges URL-Parsing und Normalisierung | Nein |
| decode-uri-component | ✅ alle | ❌ nein | ❌ still | ✅ ja | Batch-Dekodierung mit Fehlertoleranz | npm install |
| querystring.unescape() | ✅ alle | ❌ nein | ❌ still | ✅ ja | Legacy Node.js (seit v16 veraltet) | Nein (eingebaut) |
In den allermeisten Fällen reduziert sich die Wahl auf drei Szenarien. Verwende URLSearchParams zum Parsen von Query-Strings — es behandelt Dekodierung, die +-als-Leerzeichen-Regel und wiederholte Schlüssel automatisch. Verwende decodeURIComponent() (in try/catch eingeschlossen) für einen einzelnen Wert oder ein Pfadsegment, insbesondere wenn du %2F-kodierte Schrägstriche innerhalb eines Segments erwartest. Verwende decodeURI() nur, wenn du eine vollständige URL-Zeichenkette mit Nicht-ASCII-Zeichen in ihrem Pfad hast und die strukturellen Zeichen (/ ? & =) kodiert in der Ausgabe bleiben sollen.
Häufig gestellte Fragen
Verwandte Tools
Für eine Ein-Klick-Dekodierung ohne Code füge deine prozent-kodierte Zeichenkette direkt in den URL Decoder von ToolDeck ein — er dekodiert sofort im Browser, mit dem Ergebnis bereit zum Kopieren in deinen Code oder ins 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.