{"id":326,"date":"2026-07-15T14:38:52","date_gmt":"2026-07-15T12:38:52","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?page_id=326"},"modified":"2026-08-28T16:25:24","modified_gmt":"2026-08-28T14:25:24","slug":"url-pretty-print","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/","title":{"rendered":"URL Pretty Print: Anatomy, Encoding and Tracking Parameters"},"content":{"rendered":"<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 20px;\">A long URL hides three different things at once: what the address actually points at, what has been percent-encoded on the way, and which parameters are there for measurement rather than for the page. This separates all three. A host written as xn--bcher-kva is read back into letters, a value encoded twice is named as such, and the rebuilt address at the bottom is the one worth sharing.<\/p>\n<div style=\"margin-bottom: 14px;\">\n        <label for=\"up-url\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">The URL<\/label><br \/>\n        <textarea id=\"up-url\" rows=\"4\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; box-sizing: border-box; font-family: monospace; font-size: 0.82rem;\"><\/textarea>\n    <\/div>\n<div style=\"display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; margin-bottom: 14px;\">\n<div>\n            <label for=\"up-tracking\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Tracking parameters in the rebuild<\/label><br \/>\n            <select id=\"up-tracking\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; box-sizing: border-box;\"><option value=\"behalten\" selected>keep<\/option><option value=\"entfernen\">remove<\/option><\/select>\n        <\/div>\n<div>\n            <label for=\"up-ordnen\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Parameter order in the rebuild<\/label><br \/>\n            <select id=\"up-ordnen\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; box-sizing: border-box;\"><option value=\"original\" selected>as given<\/option><option value=\"alphabetisch\">alphabetical<\/option><\/select>\n        <\/div>\n<\/p><\/div>\n<p style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.82rem; margin-bottom: 16px;\">Everything runs in the browser; the address is neither transmitted nor stored. That matters here more than elsewhere, because URLs routinely carry session tokens, authorisation codes and email addresses.<\/p>\n<p>    <button id=\"up-btn\" class=\"button\" style=\"background: var(--accent, #7ee787); color: var(--on-accent, #0b1114); border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Break it down<\/button><\/p>\n<div id=\"up-ausgabe\" style=\"margin-top: 22px;\"><\/div>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"A long URL hides three different things at once: what the address actually points at, what has been percent-encoded on the way, and which parameters are there for measurement rather than for the page. This separates all three. A host written as xn--bcher-kva is read back into letters, a value encoded twice is named as such, and the rebuilt address at the bottom is the one worth sharing.\",\"label_url\":\"The URL\",\"label_tracking\":\"Tracking parameters in the rebuild\",\"label_ordnen\":\"Parameter order in the rebuild\",\"option_behalten\":\"keep\",\"option_entfernen\":\"remove\",\"option_original\":\"as given\",\"option_alphabetisch\":\"alphabetical\",\"datenschutz\":\"Everything runs in the browser; the address is neither transmitted nor stored. That matters here more than elsewhere, because URLs routinely carry session tokens, authorisation codes and email addresses.\",\"knopf\":\"Break it down\",\"beispiel\":\"https:\\\/\\\/xn--bcher-kva.Example.COM:443\\\/de\\\/b%C3%BCcher\\\/gr%C3%BCner+tee?utm_source=newsletter\\u0026utm_medium=email\\u0026gclid=EAIaIQobChMI\\u0026q=gr%C3%BCner+tee\\u0026email=anna.beispiel%40example.org\\u0026intern=id%2540kunde\\u0026ref=\\u0026ref=zweitwert#anchor=top\\u0026lang=de\",\"h_anatomie\":\"Anatomy\",\"zeile_schema\":\"Scheme\",\"zeile_benutzer\":\"User information\",\"zeile_host\":\"Host\",\"zeile_host_lesbar\":\"Host, read back\",\"zeile_port\":\"Port\",\"zeile_pfad\":\"Path\",\"zeile_abfrage\":\"Query\",\"zeile_fragment\":\"Fragment\",\"zeile_laenge\":\"Length in characters\",\"wert_keiner\":\"none\",\"wert_leer\":\"empty\",\"h_pfad\":\"Path segments\",\"spalte_nummer\":\"No.\",\"spalte_roh\":\"As written\",\"spalte_lesbar\":\"Decoded\",\"h_parameter\":\"Query parameters\",\"spalte_name\":\"Name\",\"spalte_befund\":\"Finding\",\"befund_tracking\":\"measurement\",\"befund_mehrfach\":\"name appears again\",\"befund_leer\":\"empty value\",\"befund_doppelt\":\"encoded twice\",\"befund_kaputt\":\"encoding does not decode\",\"befund_pii\":\"contains an email address\",\"befund_normal\":\"ordinary\",\"h_fragment\":\"The fragment read as parameters\",\"h_neu\":\"Rebuilt\",\"neu_abweichend\":\"The rebuilt address differs from the one given: the host is lowercased, a default port is dropped, and the chosen options are applied.\",\"h_hinweise\":\"Notes\",\"hinweis_keine_eingabe\":\"Nothing to break down yet - the address goes in the field above.\",\"hinweis_unlesbar\":\"This does not split into the parts a URL is made of.\",\"hinweis_kein_schema\":\"No scheme. Without one this is a relative reference, and where it points depends on the document it sits in.\",\"hinweis_benutzerinfo\":\"The address carries user information before the host. Credentials in a URL end up in history, logs and referrers; browsers have been stripping them for years.\",\"hinweis_punycode\":\"The host contains punycode. Read back it says: {lesbar}. Two hosts that look alike in letters can be different addresses, and one that looks foreign can be ordinary - the encoded form is the one that counts.\",\"hinweis_gross_klein\":\"The host contains uppercase letters. A host is case-insensitive, so this changes nothing; the path is case-sensitive, so there it would.\",\"hinweis_ip_literal\":\"The host is an address rather than a name. No DNS is involved, and no certificate will match unless it was issued for that address.\",\"hinweis_standardport\":\"The port is the default for this scheme and can be dropped. Written out it makes two identical addresses look different, which matters wherever URLs are compared as strings.\",\"hinweis_tracking\":\"{anzahl} parameters are measurement rather than function. Removing them changes what is recorded, not what the page shows - which is exactly why they can be dropped from an address that gets shared.\",\"hinweis_mehrfach\":\"A parameter name appears more than once. Which one wins is up to the receiving side: PHP takes the last, others take the first, and some collect an array.\",\"hinweis_leere_parameter\":\"A parameter has an empty value. That is not the same as being absent, and receiving code frequently treats it as if it were.\",\"hinweis_doppelt_kodiert\":\"A value only becomes readable after decoding twice. Somewhere on the way it was encoded once too often - usually a value that was already encoded being put through an encoder again.\",\"hinweis_kodierung_kaputt\":\"A percent sequence does not decode. Either a stray percent sign, or bytes that are not valid UTF-8.\",\"hinweis_pii\":\"An email address is in the URL. It travels in the referrer to every third party the page loads, and it lands in every server log along the way.\",\"hinweis_fragment_parameter\":\"The fragment carries what looks like parameters. The fragment is never sent to the server - it stays in the browser, which is why implicit OAuth flows used it.\",\"hinweis_plus_im_pfad\":\"The path contains a plus sign. In a query a plus means a space; in a path it means a plus. The two are read differently, and that is a common source of a wrong lookup.\",\"hinweis_lang\":\"Over 2000 characters. Some servers and proxies cut off around there, and behaviour past that point is not something any specification guarantees.\",\"hinweis_liste_unvollstaendig\":\"The list of tracking parameters is curated and cannot be complete; a parameter shown as ordinary may still be measurement from a platform not on the list.\",\"hinweis_lokal\":\"This breakdown ran entirely in the browser. The address was not sent anywhere.\"};<\/p>\n<p>    \/\/ =========================================================================\n    \/\/ Zerlegung nach RFC 3986\n    \/\/ =========================================================================\n    \/\/\n    \/\/ Bewusst nicht ueber new URL(): der eingebaute Parser normalisiert weg,\n    \/\/ was hier gerade gezeigt werden soll - er senkt den Host, loest\n    \/\/ Punktsegmente auf und wirft bei einer kaputten Adresse eine Ausnahme,\n    \/\/ statt einen Befund zu liefern.<\/p>\n<p>    var MUSTER = \/^(?:([^:\\\/?#]+):)?(?:\\\/\\\/([^\\\/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?$\/;<\/p>\n<p>    var STANDARDPORT = { http: '80', https: '443', ftp: '21', ws: '80', wss: '443' };<\/p>\n<p>    function zerlegen(adresse) {\n        var roh = String(adresse == null ? '' : adresse).replace(\/^\\s+|\\s+$\/g, '');\n        var m = roh.match(MUSTER);\n        if (!m) { return null; }\n        var autoritaet = m[2] === undefined ? null : m[2];\n        var benutzer = null, wirt = autoritaet, port = null;\n        if (autoritaet !== null) {\n            var at = autoritaet.lastIndexOf('@');\n            if (at !== -1) {\n                benutzer = autoritaet.slice(0, at);\n                wirt = autoritaet.slice(at + 1);\n            }\n            \/\/ IPv6 steht in eckigen Klammern; der Doppelpunkt darin ist kein Port.\n            var klammer = wirt.lastIndexOf(']');\n            var doppel = wirt.indexOf(':', klammer === -1 ? 0 : klammer);\n            if (doppel !== -1) {\n                port = wirt.slice(doppel + 1);\n                wirt = wirt.slice(0, doppel);\n            }\n        }\n        return {\n            roh: roh,\n            schema: m[1] === undefined ? null : m[1],\n            autoritaet: autoritaet,\n            benutzer: benutzer,\n            host: wirt === null ? null : wirt,\n            port: port,\n            pfad: m[3] === undefined ? '' : m[3],\n            abfrage: m[4] === undefined ? null : m[4],\n            fragment: m[5] === undefined ? null : m[5]\n        };\n    }<\/p>\n<p>    \/\/ =========================================================================\n    \/\/ Punycode, RFC 3492\n    \/\/ =========================================================================\n    \/\/\n    \/\/ Ein Werkzeug, das eine Adresse lesbar machen soll, darf xn--bcher-kva\n    \/\/ nicht so stehen lassen: was dort steht, ist genau die Frage.<\/p>\n<p>    function punyEntschluesseln(kennung) {\n        var BASIS = 36, TMIN = 1, TMAX = 26, SKEW = 38, DAEMPFUNG = 700,\n            ANFANGSBIAS = 72, ANFANGS_N = 128, GRENZE = 0x7FFFFFFF;<\/p>\n<p>        \/\/ Die Grenzen muessen nach unten UND nach oben gelten. Die verbreitete\n        \/\/ Kurzform (c - 48 < 10) trifft auch jedes Zeichen unterhalb der\n        \/\/ Ziffern: ein Ausrufezeichen galte dann als Ziffer 11, und der\n        \/\/ Dekodierer lieferte fuer eine kaputte Kennung ein plausibles, aber\n        \/\/ falsches Wort - bei einem Werkzeug gegen Adressverwechslung die\n        \/\/ schaedlichste Art von Fehler.\n        function ziffer(z) {\n            var c = z.charCodeAt(0);\n            if (c >= 48 && c <= 57) { return c - 22; }    \/\/ 0-9  -> 26-35\n            if (c >= 65 && c <= 90) { return c - 65; }    \/\/ A-Z  -> 0-25\n            if (c >= 97 && c <= 122) { return c - 97; }   \/\/ a-z  -> 0-25\n            return BASIS;                                  \/\/ ungueltig\n        }\n        function anpassen(delta, anzahl, ersteRunde) {\n            delta = ersteRunde ? Math.floor(delta \/ DAEMPFUNG) : (delta >> 1);\n            delta += Math.floor(delta \/ anzahl);\n            var k = 0;\n            while (delta > (((BASIS - TMIN) * TMAX) >> 1)) {\n                delta = Math.floor(delta \/ (BASIS - TMIN));\n                k += BASIS;\n            }\n            return k + Math.floor(((BASIS - TMIN + 1) * delta) \/ (delta + SKEW));\n        }<\/p>\n<p>        var s = String(kennung == null ? '' : kennung);\n        if (s.slice(0, 4).toLowerCase() !== 'xn--') { return null; }\n        var rest = s.slice(4);\n        var ausgabe = [];\n        var trenner = rest.lastIndexOf('-');\n        if (trenner > 0) {\n            for (var j = 0; j < trenner; j++) {\n                var c0 = rest.charCodeAt(j);\n                if (c0 >= 0x80) { return null; }\n                ausgabe.push(c0);\n            }\n        }\n        var n = ANFANGS_N, i = 0, bias = ANFANGSBIAS;\n        var index = trenner > 0 ? trenner + 1 : 0;\n        if (index >= rest.length) { return null; }\n        while (index < rest.length) {\n            var alt = i, w = 1, k = BASIS;\n            for (;;) {\n                if (index >= rest.length) { return null; }\n                var d = ziffer(rest.charAt(index++));\n                if (d >= BASIS) { return null; }\n                if (d > Math.floor((GRENZE - i) \/ w)) { return null; }\n                i += d * w;\n                var t = k <= bias ? TMIN : (k >= bias + TMAX ? TMAX : k - bias);\n                if (d < t) { break; }\n                if (w > Math.floor(GRENZE \/ (BASIS - t))) { return null; }\n                w *= (BASIS - t);\n                k += BASIS;\n            }\n            bias = anpassen(i - alt, ausgabe.length + 1, alt === 0);\n            if (Math.floor(i \/ (ausgabe.length + 1)) > GRENZE - n) { return null; }\n            n += Math.floor(i \/ (ausgabe.length + 1));\n            i %= (ausgabe.length + 1);\n            ausgabe.splice(i, 0, n);\n            i++;\n        }\n        var text = '';\n        for (var m2 = 0; m2 < ausgabe.length; m2++) {\n            text += String.fromCodePoint ? String.fromCodePoint(ausgabe[m2]) : String.fromCharCode(ausgabe[m2]);\n        }\n        return text;\n    }\n\n    \/\/ =========================================================================\n    \/\/ Bausteine\n    \/\/ =========================================================================\n\n    \/** Mehrfach entschluesseln, bis sich nichts mehr aendert - hoechstens dreimal. *\/\n    function ganzDekodieren(wert) {\n        var t = String(wert == null ? '' : wert);\n        for (var i = 0; i < 3; i++) {\n            var n;\n            try { n = decodeURIComponent(t.replace(\/\\+\/g, ' ')); } catch (e) { return { text: t, runden: i, kaputt: true }; }\n            if (n === t) { return { text: t, runden: i, kaputt: false }; }\n            t = n;\n        }\n        return { text: t, runden: 3, kaputt: false };\n    }\n\n    function einmalDekodieren(wert) {\n        try { return decodeURIComponent(String(wert == null ? '' : wert).replace(\/\\+\/g, ' ')); }\n        catch (e) { return null; }\n    }\n\n    var TRACKING = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'utm_id',\n        'utm_source_platform', 'utm_creative_format', 'utm_marketing_tactic',\n        'gclid', 'gbraid', 'wbraid', 'dclid', 'gclsrc', 'gad_source', 'gad_campaignid',\n        'fbclid', 'msclkid', 'ttclid', 'twclid', 'li_fat_id', 'igshid', 'yclid', 'epik',\n        'rdt_cid', 'sc_cid', 'mc_cid', 'mc_eid', 'mkt_tok', 's_kwcid', 'vero_id', '_gl',\n        'hsa_acc', 'hsa_cam', 'oly_anon_id', 'wickedid', 'ml_subscriber'];\n\n    function istTracking(name) {\n        return TRACKING.indexOf(String(name).toLowerCase()) !== -1;\n    }\n\n    var MAIL = \/[A-Za-z0-9._%+\\-]+@[A-Za-z0-9.\\-]+\\.[A-Za-z]{2,}\/;\n\n    function parameterLesen(abfrage) {\n        if (abfrage === null || abfrage === undefined) { return []; }\n        var roh = String(abfrage);\n        if (!roh.length) { return []; }\n        var gesehen = {};\n        return roh.split('&#038;').map(function (paar, nummer) {\n            if (!paar.length) {\n                return { nummer: nummer, name: '', rohWert: '', wert: '', leer: true, ohneGleich: true, tracking: false, mehrfach: false, runden: 0 };\n            }\n            var g = paar.indexOf('=');\n            var name = g === -1 ? paar : paar.slice(0, g);\n            var rohWert = g === -1 ? '' : paar.slice(g + 1);\n            var ganz = ganzDekodieren(rohWert);\n            var nameDek = einmalDekodieren(name);\n            var schluessel = (nameDek === null ? name : nameDek).toLowerCase();\n            var mehrfach = gesehen[schluessel] === true;\n            gesehen[schluessel] = true;\n            return {\n                nummer: nummer,\n                name: nameDek === null ? name : nameDek,\n                rohName: name,\n                rohWert: rohWert,\n                wert: ganz.text,\n                runden: ganz.runden,\n                kaputt: ganz.kaputt,\n                leer: rohWert.length === 0,\n                ohneGleich: g === -1,\n                tracking: istTracking(nameDek === null ? name : nameDek),\n                mehrfach: mehrfach,\n                pii: MAIL.test(ganz.text)\n            };\n        });\n    }\n\n    function hostZerlegen(host) {\n        if (host === null || host === undefined || !String(host).length) { return null; }\n        var h = String(host);\n        var istIPv6 = \/^\\[.*\\]$\/.test(h);\n        var istIPv4 = \/^\\d{1,3}(\\.\\d{1,3}){3}$\/.test(h);\n        var kennungen = (istIPv6 || istIPv4) ? [] : h.split('.');\n        var lesbar = kennungen.map(function (k) {\n            var u = punyEntschluesseln(k);\n            return u === null ? k : u;\n        });\n        return {\n            roh: h,\n            klein: h.toLowerCase(),\n            hatGrossbuchstaben: h !== h.toLowerCase(),\n            istIPv4: istIPv4,\n            istIPv6: istIPv6,\n            kennungen: kennungen,\n            lesbar: kennungen.length ? lesbar.join('.') : h,\n            hatPunycode: kennungen.some(function (k) { return punyEntschluesseln(k) !== null; })\n        };\n    }\n\n    function pfadZerlegen(pfad) {\n        var p = String(pfad == null ? '' : pfad);\n        if (!p.length) { return []; }\n        return p.split('\/').filter(function (s, i) { return !(i === 0 &#038;&#038; s === ''); }).map(function (s) {\n            var d = einmalDekodieren(s);\n            return { roh: s, lesbar: d === null ? s : d, kaputt: d === null };\n        });\n    }\n\n    function neuAufbauen(teile, parameter, optionen) {\n        var o = optionen || {};\n        var behalten = parameter.filter(function (p) {\n            if (p.ohneGleich &#038;&#038; !p.name.length) { return false; }\n            return o.tracking === 'entfernen' ? !p.tracking : true;\n        });\n        if (o.ordnen === 'alphabetisch') {\n            behalten = behalten.slice().sort(function (a, b) {\n                if (a.name === b.name) { return a.nummer - b.nummer; }\n                return a.name < b.name ? -1 : 1;\n            });\n        }\n        var abfrage = behalten.map(function (p) {\n            return p.ohneGleich ? p.rohName : p.rohName + '=' + p.rohWert;\n        }).join('&#038;');\n\n        var s = '';\n        if (teile.schema !== null) { s += teile.schema.toLowerCase() + ':'; }\n        if (teile.autoritaet !== null) {\n            s += '\/\/';\n            if (teile.benutzer !== null) { s += teile.benutzer + '@'; }\n            s += (teile.host || '').toLowerCase();\n            var standard = teile.schema ? STANDARDPORT[teile.schema.toLowerCase()] : null;\n            if (teile.port !== null &#038;&#038; teile.port !== '' &#038;&#038; teile.port !== standard) { s += ':' + teile.port; }\n        }\n        s += teile.pfad;\n        if (abfrage.length) { s += '?' + abfrage; }\n        if (teile.fragment !== null &#038;&#038; teile.fragment.length) { s += '#' + teile.fragment; }\n        return s;\n    }\n\n    \/\/ =========================================================================\n    \/\/ Auswertung\n    \/\/ =========================================================================\n\n    function auswerten(eingabe, optionen) {\n        var roh = String(eingabe == null ? '' : eingabe).replace(\/^\\s+|\\s+$\/g, '');\n        if (!roh.length) { return { leer: true, hinweise: ['keine_eingabe'] }; }\n\n        var teile = zerlegen(roh);\n        if (!teile) { return { leer: true, hinweise: ['unlesbar'] }; }\n\n        var host = hostZerlegen(teile.host);\n        var pfad = pfadZerlegen(teile.pfad);\n        var parameter = parameterLesen(teile.abfrage);\n        var fragmentParameter = (teile.fragment !== null &#038;&#038; \/[=&#038;]\/.test(teile.fragment))\n            ? parameterLesen(teile.fragment) : [];\n\n        var standard = teile.schema ? STANDARDPORT[teile.schema.toLowerCase()] : null;\n        var neu = neuAufbauen(teile, parameter, optionen);\n\n        var trackingAnzahl = parameter.filter(function (p) { return p.tracking; }).length;\n        var mehrfachAnzahl = parameter.filter(function (p) { return p.mehrfach; }).length;\n        var leerAnzahl = parameter.filter(function (p) { return p.leer &#038;&#038; !p.ohneGleich; }).length;\n        var doppeltKodiert = parameter.filter(function (p) { return p.runden > 1; }).length;\n        var kaputteKodierung = parameter.filter(function (p) { return p.kaputt; }).length\n            + pfad.filter(function (s) { return s.kaputt; }).length;\n        var piiAnzahl = parameter.filter(function (p) { return p.pii; }).length\n            + (MAIL.test(ganzDekodieren(teile.pfad).text) ? 1 : 0);<\/p>\n<p>        var hinweise = [];\n        if (teile.schema === null) { hinweise.push('kein_schema'); }\n        if (teile.benutzer !== null) { hinweise.push('benutzerinfo'); }\n        if (host && host.hatPunycode) { hinweise.push('punycode'); }\n        if (host && host.hatGrossbuchstaben) { hinweise.push('gross_klein'); }\n        if (host && (host.istIPv4 || host.istIPv6)) { hinweise.push('ip_literal'); }\n        if (teile.port !== null && teile.port === standard) { hinweise.push('standardport'); }\n        if (trackingAnzahl) { hinweise.push('tracking'); }\n        if (mehrfachAnzahl) { hinweise.push('mehrfach'); }\n        if (leerAnzahl) { hinweise.push('leere_parameter'); }\n        if (doppeltKodiert) { hinweise.push('doppelt_kodiert'); }\n        if (kaputteKodierung) { hinweise.push('kodierung_kaputt'); }\n        if (piiAnzahl) { hinweise.push('pii'); }\n        if (fragmentParameter.length) { hinweise.push('fragment_parameter'); }\n        if (teile.pfad.indexOf('+') !== -1) { hinweise.push('plus_im_pfad'); }\n        if (roh.length > 2000) { hinweise.push('lang'); }\n        hinweise.push('liste_unvollstaendig');\n        hinweise.push('lokal');<\/p>\n<p>        return {\n            leer: false,\n            teile: teile,\n            host: host,\n            pfad: pfad,\n            parameter: parameter,\n            fragmentParameter: fragmentParameter,\n            standardport: standard,\n            neu: neu,\n            zaehlung: {\n                laenge: roh.length,\n                parameter: parameter.length,\n                tracking: trackingAnzahl,\n                mehrfach: mehrfachAnzahl,\n                leer: leerAnzahl,\n                doppeltKodiert: doppeltKodiert,\n                pii: piiAnzahl,\n                segmente: pfad.length\n            },\n            hinweise: hinweise\n        };\n    }<\/p>\n<p>    \/\/ --- Pruefpunkt ----------------------------------------------------------\n    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.UP = {\n        auswerten: auswerten,\n        zerlegen: zerlegen,\n        punyEntschluesseln: punyEntschluesseln,\n        hostZerlegen: hostZerlegen,\n        pfadZerlegen: pfadZerlegen,\n        parameterLesen: parameterLesen,\n        neuAufbauen: neuAufbauen,\n        ganzDekodieren: ganzDekodieren,\n        istTracking: istTracking,\n        TRACKING: TRACKING,\n        STANDARDPORT: STANDARDPORT,\n        T: T\n    };<\/p>\n<p>    \/\/ =========================================================================\n    \/\/ Oberflaeche\n    \/\/ =========================================================================<\/p>\n<p>    var btn = document.getElementById('up-btn');\n    var out = document.getElementById('up-ausgabe');\n    if (!btn || !out) { return; }<\/p>\n<p>    var feld = document.getElementById('up-url');\n    if (feld && !feld.value) { feld.value = T.beispiel; }<\/p>\n<p>    function el(tag, stil, text) {\n        var e = document.createElement(tag);\n        if (stil) { e.setAttribute('style', stil); }\n        if (text !== undefined) { e.textContent = text; }\n        return e;\n    }\n    function wert(id) { var e = document.getElementById(id); return e ? e.value : ''; }<\/p>\n<p>    var UEBERSCHRIFT = 'font-family: \"Nunito Sans\", sans-serif; font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.92rem; margin: 18px 0 8px;';\n    var ZELLE = 'padding: 5px 12px 5px 0; color: var(--text-secondary, #a0a0b0); font-size: 0.87rem;';\n    var ZELLE_WERT = 'padding: 5px 12px 5px 0; color: var(--text-primary, #e8e8ee); font-size: 0.87rem; font-family: monospace; word-break: break-all;';\n    var VORFORM = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 6px; padding: 10px; color: var(--text-primary, #e8e8ee); font-family: monospace; font-size: 0.8rem; white-space: pre-wrap; word-break: break-all; margin: 0;';\n    var GUT = ' color: #7ee787;';\n    var WARN = ' color: #ffa94d;';\n    var GRAU = ' color: #8a8a99;';<\/p>\n<p>    function gitter(spalten) {\n        return el('div', 'display: grid; grid-template-columns: ' + spalten + '; gap: 0 18px; align-items: baseline;');\n    }\n    function paar(g, name, w, stil) {\n        g.appendChild(el('div', ZELLE, name));\n        g.appendChild(el('div', ZELLE_WERT + (stil || ''), w));\n    }\n    function kopf(g, spalten) {\n        spalten.forEach(function (s) {\n            g.appendChild(el('div', ZELLE + ' font-weight: 700; color: var(--text-primary, #e8e8ee);', s));\n        });\n    }<\/p>\n<p>    btn.addEventListener('click', function () {\n        var erg = auswerten(wert('up-url'), { tracking: wert('up-tracking'), ordnen: wert('up-ordnen') });\n        out.innerHTML = '';<\/p>\n<p>        if (erg.leer) {\n            var liste0 = el('ul', 'margin: 0 0 0 18px; padding: 0; color: var(--text-secondary, #a0a0b0); font-size: 0.87rem; line-height: 1.65;');\n            erg.hinweise.forEach(function (h) {\n                if (T['hinweis_' + h]) { liste0.appendChild(el('li', '', T['hinweis_' + h])); }\n            });\n            out.appendChild(liste0);\n            return;\n        }<\/p>\n<p>        \/\/ --- Anatomie ---\n        out.appendChild(el('div', UEBERSCHRIFT, T.h_anatomie));\n        var g = gitter('auto auto');\n        function teil(name, w, stil) { paar(g, name, (w === null || w === '') ? T.wert_keiner : w, (w === null || w === '') ? GRAU : (stil || '')); }\n        teil(T.zeile_schema, erg.teile.schema);\n        teil(T.zeile_benutzer, erg.teile.benutzer, WARN);\n        teil(T.zeile_host, erg.teile.host);\n        if (erg.host && erg.host.hatPunycode) { paar(g, T.zeile_host_lesbar, erg.host.lesbar, GUT); }\n        teil(T.zeile_port, erg.teile.port, erg.teile.port === erg.standardport ? GRAU : '');\n        teil(T.zeile_pfad, erg.teile.pfad);\n        teil(T.zeile_abfrage, erg.teile.abfrage);\n        teil(T.zeile_fragment, erg.teile.fragment);\n        paar(g, T.zeile_laenge, String(erg.zaehlung.laenge), erg.zaehlung.laenge > 2000 ? WARN : '');\n        out.appendChild(g);<\/p>\n<p>        \/\/ --- Pfad ---\n        if (erg.pfad.length) {\n            out.appendChild(el('div', UEBERSCHRIFT, T.h_pfad));\n            var gp = gitter('auto auto auto');\n            kopf(gp, [T.spalte_nummer, T.spalte_roh, T.spalte_lesbar]);\n            erg.pfad.forEach(function (s, i) {\n                gp.appendChild(el('div', ZELLE_WERT, String(i + 1)));\n                gp.appendChild(el('div', ZELLE_WERT, s.roh));\n                gp.appendChild(el('div', ZELLE_WERT + (s.roh === s.lesbar ? GRAU : GUT), s.lesbar));\n            });\n            out.appendChild(gp);\n        }<\/p>\n<p>        \/\/ --- Parameter ---\n        if (erg.parameter.length) {\n            out.appendChild(el('div', UEBERSCHRIFT, T.h_parameter));\n            var gq = gitter('auto auto auto auto');\n            kopf(gq, [T.spalte_name, T.spalte_roh, T.spalte_lesbar, T.spalte_befund]);\n            erg.parameter.forEach(function (p) {\n                gq.appendChild(el('div', ZELLE_WERT, p.name || T.wert_keiner));\n                gq.appendChild(el('div', ZELLE_WERT + GRAU, p.rohWert || T.wert_leer));\n                gq.appendChild(el('div', ZELLE_WERT, p.wert || T.wert_leer));\n                var b = [];\n                if (p.tracking) { b.push(T.befund_tracking); }\n                if (p.mehrfach) { b.push(T.befund_mehrfach); }\n                if (p.leer && !p.ohneGleich) { b.push(T.befund_leer); }\n                if (p.runden > 1) { b.push(T.befund_doppelt); }\n                if (p.kaputt) { b.push(T.befund_kaputt); }\n                if (p.pii) { b.push(T.befund_pii); }\n                gq.appendChild(el('div', ZELLE + (b.length ? WARN : GRAU), b.length ? b.join(', ') : T.befund_normal));\n            });\n            out.appendChild(gq);\n        }<\/p>\n<p>        \/\/ --- Fragment als Parameter ---\n        if (erg.fragmentParameter.length) {\n            out.appendChild(el('div', UEBERSCHRIFT, T.h_fragment));\n            var gf = gitter('auto auto');\n            erg.fragmentParameter.forEach(function (p) {\n                paar(gf, p.name || T.wert_keiner, p.wert || T.wert_leer);\n            });\n            out.appendChild(gf);\n        }<\/p>\n<p>        \/\/ --- Neuaufbau ---\n        out.appendChild(el('div', UEBERSCHRIFT, T.h_neu));\n        out.appendChild(el('pre', VORFORM, erg.neu));\n        if (erg.neu !== erg.teile.roh) {\n            out.appendChild(el('p', ZELLE + ' margin: 8px 0 0;', T.neu_abweichend));\n        }<\/p>\n<p>        \/\/ --- Hinweise ---\n        out.appendChild(el('div', UEBERSCHRIFT, T.h_hinweise));\n        var liste = el('ul', 'margin: 0 0 0 18px; padding: 0; color: var(--text-secondary, #a0a0b0); font-size: 0.87rem; line-height: 1.65;');\n        erg.hinweise.forEach(function (h) {\n            var text = T['hinweis_' + h];\n            if (!text) { return; }\n            liste.appendChild(el('li', '', text\n                .replace('{lesbar}', erg.host ? erg.host.lesbar : '')\n                .replace('{anzahl}', String(erg.zaehlung.tracking))));\n        });\n        out.appendChild(liste);\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Breaks a URL into every part it is made of, decodes what is encoded, says which parameters are measurement rather than function, reads punycode hosts back into letters, and rebuilds a clean address. Nothing leaves the browser.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":38,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[91279,91144,91516],"class_list":["post-326","page","type-page","status-publish","hentry","tag-prywatnosc-danych-pl","tag-devops","tag-tracking"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>URL Pretty Print: Anatomy, Encoding and Tracking Parameters - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"URL Pretty Print: Anatomy, Encoding and Tracking Parameters - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Breaks a URL into every part it is made of, decodes what is encoded, says which parameters are measurement rather than function, reads punycode hosts back into letters, and rebuilds a clean address. Nothing leaves the browser.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-28T14:25:24+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/url-pretty-print\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/url-pretty-print\\\/\",\"name\":\"URL Pretty Print: Anatomy, Encoding and Tracking Parameters - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-07-15T12:38:52+00:00\",\"dateModified\":\"2026-08-28T14:25:24+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/url-pretty-print\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/url-pretty-print\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/url-pretty-print\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"URL Pretty Print: Anatomy, Encoding and Tracking Parameters\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"URL Pretty Print: Anatomy, Encoding and Tracking Parameters - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/","og_locale":"en_US","og_type":"article","og_title":"URL Pretty Print: Anatomy, Encoding and Tracking Parameters - Lukas Wojcik - Blog","og_description":"Breaks a URL into every part it is made of, decodes what is encoded, says which parameters are measurement rather than function, reads punycode hosts back into letters, and rebuilds a clean address. Nothing leaves the browser.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-08-28T14:25:24+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/","name":"URL Pretty Print: Anatomy, Encoding and Tracking Parameters - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-07-15T12:38:52+00:00","dateModified":"2026-08-28T14:25:24+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/url-pretty-print\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/"},{"@type":"ListItem","position":3,"name":"URL Pretty Print: Anatomy, Encoding and Tracking Parameters"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/326","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=326"}],"version-history":[{"count":4,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/326\/revisions"}],"predecessor-version":[{"id":13114,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/326\/revisions\/13114"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/38"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=326"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=326"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}