{"id":15550,"date":"2026-09-05T13:30:58","date_gmt":"2026-09-05T11:30:58","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/"},"modified":"2026-09-05T13:30:58","modified_gmt":"2026-09-05T11:30:58","slug":"compression-negotiation-checker-gzip-brotli-zstd","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/","title":{"rendered":"Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd"},"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;\">Ein Browser nennt in Accept-Encoding, was er entpacken kann, und der Server w\u00e4hlt eine Kodierung. Welche das ist und wie viel sie spart, ist an der Seite selbst nicht zu sehen. Diese Pr\u00fcfung ruft dieselbe Adresse f\u00fcnfmal von diesem Server ab: einmal unkomprimiert als Bezug, je einmal nur mit gzip, Brotli und zstd, und einmal mit dem kombinierten Header, den aktuelle Browser senden. F\u00fcr jede Antwort z\u00e4hlt sie die Bytes auf der Leitung gegen die entpackte Gr\u00f6\u00dfe und liest Content-Encoding, Vary und ETag.<\/p>\n<div style=\"margin-bottom: 14px;\">\n        <label for=\"cp-url\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Adresse (eine Seite, ein Skript, ein Stylesheet oder ein Bild)<\/label><br \/>\n        <input id=\"cp-url\" type=\"text\" value=\"https:\/\/www.wikipedia.org\/\" 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;\">\n    <\/div>\n<p style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.82rem; margin-bottom: 16px;\">Von diesem Server gehen Weiterleitungen und f\u00fcnf vollst\u00e4ndige Abrufe von je bis zu 3 MB an die eingegebene Adresse. Hosts in privaten, Loopback- und Link-local-Netzen werden abgelehnt. Die Abfrage ist durch reCAPTCHA v3 gesch\u00fctzt; die aufrufende IP-Adresse und das Ziel werden eine Stunde lang gespeichert, um die Rate zu begrenzen.<\/p>\n<p>    <button id=\"cp-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;\">Kompression pr\u00fcfen<\/button><\/p>\n<div id=\"cp-ausgabe\" style=\"margin-top: 22px;\"><\/div>\n<p style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.8rem; margin: 24px 0 0;\">Grenzen, die dazugeh\u00f6ren: Gepr\u00fcft wird nur eine der aufgel\u00f6sten Adressen; ein CDN komprimiert je Standort wom\u00f6glich anders oder erst nach dem ersten Fehlgriff im Cache; die Zeiten sind Einzelmessungen und spiegeln vor allem \u00dcbertragungsgr\u00f6\u00dfe und Entfernung; Inhalte \u00fcber 3 MB werden abgeschnitten, ihre Verh\u00e4ltnisse sind dann nur n\u00e4herungsweise; und ein Server, der zur Laufzeit komprimiert, kann bei jedem Lauf leicht andere Bytezahlen zeigen.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Ein Browser nennt in Accept-Encoding, was er entpacken kann, und der Server w\u00e4hlt eine Kodierung. Welche das ist und wie viel sie spart, ist an der Seite selbst nicht zu sehen. Diese Pr\u00fcfung ruft dieselbe Adresse f\u00fcnfmal von diesem Server ab: einmal unkomprimiert als Bezug, je einmal nur mit gzip, Brotli und zstd, und einmal mit dem kombinierten Header, den aktuelle Browser senden. F\u00fcr jede Antwort z\u00e4hlt sie die Bytes auf der Leitung gegen die entpackte Gr\u00f6\u00dfe und liest Content-Encoding, Vary und ETag.\",\"label_url\":\"Adresse (eine Seite, ein Skript, ein Stylesheet oder ein Bild)\",\"datenschutz\":\"Von diesem Server gehen Weiterleitungen und f\u00fcnf vollst\u00e4ndige Abrufe von je bis zu 3 MB an die eingegebene Adresse. Hosts in privaten, Loopback- und Link-local-Netzen werden abgelehnt. Die Abfrage ist durch reCAPTCHA v3 gesch\u00fctzt; die aufrufende IP-Adresse und das Ziel werden eine Stunde lang gespeichert, um die Rate zu begrenzen.\",\"knopf\":\"Kompression pr\u00fcfen\",\"laeuft\":\"Die f\u00fcnf Abrufe laufen...\",\"grenze\":\"Grenzen, die dazugeh\u00f6ren: Gepr\u00fcft wird nur eine der aufgel\u00f6sten Adressen; ein CDN komprimiert je Standort wom\u00f6glich anders oder erst nach dem ersten Fehlgriff im Cache; die Zeiten sind Einzelmessungen und spiegeln vor allem \u00dcbertragungsgr\u00f6\u00dfe und Entfernung; Inhalte \u00fcber 3 MB werden abgeschnitten, ihre Verh\u00e4ltnisse sind dann nur n\u00e4herungsweise; und ein Server, der zur Laufzeit komprimiert, kann bei jedem Lauf leicht andere Bytezahlen zeigen.\",\"h_antwort\":\"Antwort\",\"zeile_url\":\"Gemessene Adresse\",\"zeile_ip\":\"Aufgel\u00f6ste Adressen\",\"zeile_server\":\"Server-Header\",\"zeile_typ\":\"Inhaltstyp\",\"zeile_basis\":\"Entpackte Gr\u00f6\u00dfe\",\"zeile_dauer\":\"Dauer\",\"zeile_limit\":\"Pr\u00fcfungen in dieser Stunde noch\",\"klasse_text\":\"komprimierbar\",\"klasse_schon_komprimiert\":\"durch das Format schon komprimiert\",\"klasse_unbekannt\":\"unbekannt\",\"h_varianten\":\"F\u00fcnf Anfragen, eine Adresse\",\"spalte_accept\":\"Gesendetes Accept-Encoding\",\"spalte_kodierung\":\"Content-Encoding\",\"spalte_leitung\":\"Auf der Leitung\",\"spalte_anteil\":\"Vom Entpackten\",\"spalte_status\":\"Status\",\"spalte_ttfb\":\"Erstes Byte\",\"spalte_gesamt\":\"Gesamt\",\"variante_identity\":\"identity\",\"variante_gzip\":\"gzip\",\"variante_br\":\"br\",\"variante_zstd\":\"zstd\",\"variante_browser\":\"gzip, deflate, br, zstd\",\"gekappt_kurz\":\"(bei 3 MB abgeschnitten)\",\"fehlgeschlagen\":\"fehlgeschlagen\",\"h_befunde\":\"Befunde\",\"stufe_hoch\":\"Hoch\",\"stufe_mittel\":\"Mittel\",\"stufe_niedrig\":\"Niedrig\",\"stufe_info\":\"Hinweis\",\"stufe_gut\":\"In Ordnung\",\"keine_befunde\":\"Nichts zu berichten.\",\"urteil_gut\":\"Die Kompression wird so ausgehandelt, wie Browser es erwarten.\",\"urteil_warnung\":\"Kompression funktioniert, mit etwas, das Bytes kostet oder Caches verwirrt.\",\"urteil_kritisch\":\"Gar keine Kompression, oder die Adresse lie\u00df sich nicht abrufen.\",\"fehler_kein_token\":\"Die Pr\u00fcfung konnte nicht starten, weil reCAPTCHA nicht geladen wurde.\",\"fehler_captcha\":\"reCAPTCHA hat die Anfrage als automatisiert eingestuft. Ein Neuladen der Seite hilft in der Regel.\",\"fehler_zu_viele\":\"Die Grenze von {limit} Pr\u00fcfungen je Stunde f\u00fcr diese Adresse ist erreicht.\",\"fehler_adresse\":\"Diese Adresse l\u00e4sst sich nicht verwenden.\",\"fehler_zu_viele_spruenge\":\"Die Adresse leitet mehr als f\u00fcnfmal weiter; die Kette wurde nicht weiter verfolgt.\",\"fehler_zaehler\":\"Der Z\u00e4hler ist nicht erreichbar, deshalb wurde nichts gepr\u00fcft.\",\"fehler_pruefdienst\":\"Der reCAPTCHA-Dienst war nicht erreichbar.\",\"fehler_aufbau\":\"Der Dienst ist nicht richtig eingerichtet. Der Fehler liegt auf dieser Seite.\",\"fehler_eingabe\":\"Die Anfrage war nicht lesbar.\",\"fehler_methode\":\"Falsche Anfragemethode.\",\"fehler_netz\":\"Der Dienst war nicht erreichbar.\",\"fehler_antwort\":\"Die Antwort war nicht lesbar.\",\"fehler_unbekannt\":\"Etwas ging schief, wof\u00fcr es keine eigene Meldung gibt.\",\"grund_leer\":\"Es wurde nichts eingegeben.\",\"grund_zu_lang\":\"Die Eingabe ist zu lang.\",\"grund_unlesbar\":\"Das ist keine lesbare Adresse.\",\"grund_schema\":\"Gepr\u00fcft werden nur http- und https-Adressen.\",\"grund_benutzerinfo\":\"Eingaben mit Zugangsdaten werden abgelehnt.\",\"grund_kein_punkt\":\"Der Hostname braucht mindestens einen Punkt.\",\"grund_hostform\":\"Es wird ein Hostname gebraucht, keine IP-Adresse.\",\"grund_port\":\"Gepr\u00fcft werden nur die Ports 80, 443, 8080 und 8443.\",\"grund_gesperrter_bereich\":\"Dieser Host l\u00f6st in ein privates oder reserviertes Netz auf. Solche werden nie kontaktiert.\",\"grund_kein_dns\":\"Der Hostname l\u00e4sst sich nicht aufl\u00f6sen.\",\"grund_abruf\":\"Die Adresse hat nicht geantwortet.\",\"befund_weiterleitung\":\"{n}-mal weitergeleitet auf {ziel} || Die Messungen beziehen sich auf die Endadresse der Kette.\",\"befund_abruf_fehlgeschlagen\":\"Die Adresse antwortet nicht || Keine der f\u00fcnf Anfragen hat eine Antwort ergeben: {fehler}.\",\"befund_status_fehler\":\"Der Server hat mit Status {status} geantwortet || Gemessen wird die Kompression einer Fehlerseite, nicht der gemeinten Ressource.\",\"befund_gekappt\":\"Inhalt bei {mb} MB abgeschnitten || Der unkomprimierte Bezug ist gr\u00f6\u00dfer als die Grenze; die Verh\u00e4ltnisse gelten f\u00fcr die ersten {mb} MB und sind nur n\u00e4herungsweise.\",\"befund_kompression_erzwungen\":\"Komprimiert, obwohl identity angefragt war ({kodierung}) || Der Server ignoriert Accept-Encoding und sendet in jedem Fall {kodierung}. Clients, die das nicht entpacken k\u00f6nnen, darunter manche \u00dcberwachungswerkzeuge und alte Bibliotheken, bekommen unlesbare Bytes.\",\"befund_inhalt_verschieden\":\"Die f\u00fcnf Antworten unterscheiden sich im Inhalt ({n} Fassungen) || Nach dem Entpacken sind die Inhalte nicht identisch. Dynamische Inhalte, Token je Anfrage oder A\\\/B-Varianten \u00e4ndern sich zwischen den Anfragen; die Bytezahlen vergleichen also leicht verschiedene Seiten.\",\"befund_typ_schon_komprimiert\":\"Inhaltstyp {typ} ist durch sein Format komprimiert || Bilder, Video, Schriften in WOFF2 und Archive sind bereits komprimiert; gzip oder Brotli obendrauf spart nichts und kostet CPU. Das Fehlen von Content-Encoding ist hier richtig.\",\"befund_unnoetig_komprimiert\":\"{kodierung} auf ein bereits komprimiertes Format angewandt ({prozent} % des Originals) || Der Server komprimiert eine Ressource, deren Format schon komprimiert ist. Die Ersparnis ist null, und jede Antwort kostet Rechenzeit auf dem Server und im Browser. Diese Inhaltstypen aus der Kompressionsregel auszunehmen ist die \u00fcbliche Abhilfe.\",\"befund_typ_unbekannt\":\"Inhaltstyp {typ} nicht eingeordnet || Ob Kompression f\u00fcr diesen Typ sinnvoll ist, kennt diese Pr\u00fcfung nicht; die Bytezahlen gelten trotzdem.\",\"befund_kleine_antwort\":\"Kleine Antwort: {bytes} Bytes || Unter etwa 1 KB lohnt Kompression kaum; die Kopfzeilen wiegen mehr als die Ersparnis. Viele Server lassen sie bei kleinen Inhalten absichtlich weg.\",\"befund_groesse\":\"Entpackte Gr\u00f6\u00dfe {kb} KB ({bytes} Bytes) || Der Bezug, auf den sich jedes Verh\u00e4ltnis unten bezieht.\",\"befund_gzip_ok\":\"gzip: {prozent} % der entpackten Gr\u00f6\u00dfe ({kb} KB) || Jeder Client unterst\u00fctzt gzip. Das ist die Grundlinie, die jede komprimierte Seite erreichen sollte.\",\"befund_gzip_andere\":\"gzip angefragt, {kodierung} bekommen || Der Server hat mit einer Kodierung geantwortet, die nicht angeboten war. Clients, die nur gzip angefragt haben, k\u00f6nnen sie nicht entpacken.\",\"befund_gzip_fehlt\":\"Kein gzip f\u00fcr {kb} KB komprimierbaren Inhalt || Eine Anfrage nur mit gzip hat einen unkomprimierten Inhalt bekommen. gzip unterst\u00fctzt jeder Browser und jeder Proxy seit den Neunzigern; es wegzulassen kostet die ganze Ersparnis f\u00fcr die Mehrheit der Clients.\",\"befund_br_ok\":\"Brotli: {prozent} % der entpackten Gr\u00f6\u00dfe ({kb} KB) || Brotli unterst\u00fctzen alle aktuellen Browser \u00fcber https; bei Text spart es gegen\u00fcber gzip typischerweise 10 bis 20 %.\",\"befund_br_groesser_als_gzip\":\"Brotli um {prozent} % gr\u00f6\u00dfer als gzip || Brotli auf niedriger Qualit\u00e4tsstufe oder zur Laufzeit mit kleinem Fenster kann gegen ein gut eingestelltes gzip verlieren. Statische Vorkompression mit Qualit\u00e4t 11 ist der Fall, in dem Brotli gl\u00e4nzt.\",\"befund_br_gegen_gzip\":\"Brotli spart {prozent} % gegen\u00fcber gzip || Der Unterschied der beiden komprimierten Gr\u00f6\u00dfen f\u00fcr diese Ressource.\",\"befund_br_fehlt\":\"Kein Brotli || Eine Anfrage nur mit Brotli hat einen unkomprimierten Inhalt bekommen. Jeder aktuelle Browser sendet br in Accept-Encoding \u00fcber https; es einzuschalten (mod_brotli, ngx_brotli oder der Schalter im CDN) verkleinert Text\u00fcbertragungen gegen\u00fcber gzip typischerweise um weitere 10 bis 20 %.\",\"befund_br_ersetzt\":\"Brotli angefragt, {kodierung} bekommen || Der Server bietet kein Brotli und hat mit einer anderen, nicht angefragten Kodierung geantwortet. Strenge Clients lehnen das ab.\",\"befund_zstd_ok\":\"zstd: {prozent} % der entpackten Gr\u00f6\u00dfe ({kb} KB) || Zstandard komprimiert etwa so gut wie Brotli und entpackt schneller. Chrome und Firefox senden zstd in Accept-Encoding seit 2024; Safari nicht.\",\"befund_zstd_fehlt\":\"Kein zstd || Heute optional: Chrome und Firefox nehmen es an, Safari nicht, und der Gewinn gegen\u00fcber Brotli ist bei typischen Seiten klein. Lohnt vor allem bei sehr gro\u00dfen oder h\u00e4ufig wechselnden Antworten.\",\"befund_zstd_ersetzt\":\"zstd angefragt, {kodierung} bekommen || Der Server bietet kein zstd und hat mit einer anderen, nicht angefragten Kodierung geantwortet.\",\"befund_browser_wahl_keine\":\"Ein Browser bekommt keine Kompression, obwohl {bestes} verf\u00fcgbar ist || Mit dem kombinierten Header aktueller Browser hat der Server unkomprimiert geantwortet, obwohl er bei einer einzelnen Kodierung komprimiert hat. Die Aushandlung bevorzugt bei mehreren Angeboten identity; das ist ein Konfigurationsfehler.\",\"befund_browser_wahl_keine_moeglich\":\"Ein Browser bekommt keine Kompression || Der kombinierte Header hat keinen komprimierten Inhalt ergeben, passend zu den Einzelanfragen.\",\"befund_browser_wahl_schlechter\":\"Ein Browser bekommt {wahl}, obwohl {bestes} um {prozent} % kleiner w\u00e4re || Mit dem kombinierten Header hat der Server {wahl} gew\u00e4hlt. {bestes} bietet er auch, aber nur, wenn es allein angefragt wird. In Apache ist das die Reihenfolge von mod_deflate und mod_brotli; in nginx muss brotli neben gzip eingeschaltet sein; ein CDN braucht die Einstellung wom\u00f6glich je Inhaltstyp.\",\"befund_browser_wahl\":\"Ein Browser bekommt {wahl} ({prozent} % der entpackten Gr\u00f6\u00dfe) || Der kombinierte Header aktueller Browser hat die beste Kodierung ergeben, die der Server anbietet.\",\"befund_verhaeltnis_schwach\":\"Schwaches Verh\u00e4ltnis: bestenfalls {prozent} % der entpackten Gr\u00f6\u00dfe || Text schrumpft \u00fcblicherweise auf 20 bis 35 %. Ein Verh\u00e4ltnis so nah an 100 % hei\u00dft: Der Inhalt ist bereits kompakt, eingebettete Bin\u00e4rdaten \u00fcberwiegen, oder die Kompressionsstufe ist sehr niedrig.\",\"befund_vary_stern\":\"Vary: * || Ein Platzhalter in Vary macht die Antwort f\u00fcr geteilte Caches unspeicherbar. War Accept-Encoding gemeint, reicht es, diesen Header zu nennen.\",\"befund_vary_ok\":\"Vary: {vary} || Caches halten je Kodierung eine Kopie und geben keinen Brotli-Inhalt an einen Client, der gzip angefragt hat.\",\"befund_vary_fehlt\":\"Vary ohne Accept-Encoding (gefunden: {vary}) || Komprimierte Antworten ohne Vary: Accept-Encoding lassen einen geteilten Cache eine Variante speichern und an jeden Client ausliefern, auch an einen, der sie nicht entpacken kann. Browser und CDNs sind heute nachsichtig, Proxys und \u00e4ltere Caches nicht.\",\"befund_etag_gleich\":\"Gleicher ETag f\u00fcr alle Kodierungen ({etag}) || Bedingte Anfragen k\u00f6nnen die Kodierungen nicht auseinanderhalten. Ein Client, der die gzip-Variante gespeichert hat, bekommt wom\u00f6glich ein 304 auf eine Brotli-Anfrage. Apache h\u00e4ngt aus diesem Grund -gzip und -br an den ETag.\",\"befund_etag_je_kodierung\":\"ETag je Kodierung verschieden || Jede Kodierung tr\u00e4gt ihren eigenen Validator, bedingte Anfragen bleiben eindeutig.\",\"befund_chunked\":\"St\u00fcckweise \u00dcbertragung (chunked) || Der komprimierte Inhalt wird ohne Content-Length gestreamt; der Server komprimiert zur Laufzeit. Die Bytezahl stammt aus den empfangenen Bytes, nicht aus einer Kopfzeile.\",\"befund_content_length\":\"Content-Length {bytes} || Die komprimierte Gr\u00f6\u00dfe steht vorab fest, typisch f\u00fcr vorkomprimierte Dateien oder ein CDN, das aus dem Cache liefert.\",\"befund_keine_kompression\":\"Gar keine Kompression f\u00fcr {kb} KB komprimierbaren Inhalt || Keine der Anfragen hat einen komprimierten Inhalt bekommen. Bei Text hei\u00dft das drei- bis f\u00fcnfmal mehr Bytes als n\u00f6tig bei jedem Besuch.\",\"befund_zeit_vergleich\":\"Gesamtzeit: unkomprimiert {identity} ms, {kodierung} {kodiert} ms || Einzelmessungen von einem nahen Server \u00fcber eine schnelle Leitung; der Unterschied w\u00e4chst mit der Entfernung und in Mobilfunknetzen, wo die Bytezahl z\u00e4hlt.\"};<\/p>\n<p>    var ENDPUNKT = '\/lw-compcheck.php';\n    var SITEKEY = '6LcrPkEtAAAAAPo1QCOf-IIM2fCL0UfdJz4y2iSY';\n    var STUFEN = ['hoch', 'mittel', 'niedrig', 'info', 'gut'];\n    var VARIANTEN = ['identity', 'gzip', 'br', 'zstd', 'browser'];\n    var KLASSEN = ['text', 'schon_komprimiert', 'unbekannt'];<\/p>\n<p>    function liste(w) { return Array.isArray(w) ? w : []; }\n    function zahl(w) { return (typeof w === 'number' && isFinite(w)) ? w : null; }\n    function text(schluessel, daten) {\n        var t = T[schluessel];\n        if (typeof t !== 'string') { return null; }\n        return t.replace(\/\\{([a-z_0-9]+)\\}\/g, function (m, k) {\n            return (daten && daten[k] !== undefined && daten[k] !== null) ? String(daten[k]) : m;\n        });\n    }\n    function kb(bytes) {\n        if (bytes === null) { return '-'; }\n        if (bytes < 1024) { return bytes + ' B'; }\n        if (bytes < 1048576) { return (Math.round(bytes \/ 102.4) \/ 10) + ' KB'; }\n        return (Math.round(bytes \/ 104857.6) \/ 10) + ' MB';\n    }\n\n    function abruf(r) {\n        r = (r &#038;&#038; typeof r === 'object') ? r : {};\n        return { accept: r.accept ? String(r.accept) : '', ok: !!r.ok, status: zahl(r.status), fehler: r.fehler ? String(r.fehler) : null,\n                 kodierung: r.kodierung ? String(r.kodierung) : null, leitung: zahl(r.leitung), entpackt: zahl(r.entpackt), prozent: zahl(r.prozent),\n                 contentLength: zahl(r.content_length), gekappt: !!r.gekappt, ttfb: zahl(r.ttfb_ms), gesamt: zahl(r.gesamt_ms) };\n    }\n\n    function bewerten(antwort) {\n        var a = antwort || {};\n        if (a.fehler) { return { fehler: String(a.fehler), grund: a.grund || null, limit: zahl(a.limit), kette: liste(a.kette) }; }\n        var befunde = liste(a.befunde).map(function (f) {\n            return { key: String(f.key || ''), stufe: STUFEN.indexOf(f.stufe) === -1 ? 'info' : f.stufe, daten: (f.daten &#038;&#038; typeof f.daten === 'object') ? f.daten : {} };\n        });\n        var gruppen = {};\n        STUFEN.forEach(function (s) { gruppen[s] = befunde.filter(function (f) { return f.stufe === s; }); });\n        var abrufe = {};\n        VARIANTEN.forEach(function (v) { abrufe[v] = abruf(a.abrufe ? a.abrufe[v] : null); });\n        return {\n            fehler: null, url: a.url ? String(a.url) : '', host: a.host ? String(a.host) : '', ip: a.ip ? String(a.ip) : '', ips: liste(a.ips), server: a.server ? String(a.server) : null,\n            urteil: (a.urteil === 'gut' || a.urteil === 'warnung' || a.urteil === 'kritisch') ? a.urteil : 'kritisch',\n            klasse: KLASSEN.indexOf(a.klasse) === -1 ? 'unbekannt' : a.klasse,\n            contentType: a.content_type ? String(a.content_type) : null, basis: zahl(a.basis) || 0,\n            abrufe: abrufe, befunde: befunde, gruppen: gruppen,\n            kette: liste(a.kette), dauer: zahl(a.dauer_ms), limitRest: zahl(a.limit_rest)\n        };\n    }\n\n    function skriptLaden() {\n        return new Promise(function (auf) {\n            if (window.grecaptcha) { auf(true); return; }\n            var s = document.createElement('script');\n            s.src = 'https:\/\/www.google.com\/recaptcha\/api.js?render=' + SITEKEY;\n            s.onload = function () { auf(true); }; s.onerror = function () { auf(false); };\n            document.head.appendChild(s);\n            setTimeout(function () { auf(!!window.grecaptcha); }, 8000);\n        });\n    }\n    function tokenHolen() {\n        return skriptLaden().then(function (da) {\n            if (!da || !window.grecaptcha || !window.grecaptcha.ready) { return null; }\n            return new Promise(function (auf) {\n                var fertig = false;\n                function einmal(w) { if (!fertig) { fertig = true; auf(w); } }\n                setTimeout(function () { einmal(null); }, 12000);\n                try {\n                    window.grecaptcha.ready(function () {\n                        if (fertig) { return; }\n                        if (!window.grecaptcha.execute) { einmal(null); return; }\n                        window.grecaptcha.execute(SITEKEY, { action: 'compcheck' }).then(function (t) { einmal(t || null); }, function () { einmal(null); });\n                    });\n                } catch (e) { einmal(null); }\n            });\n        }, function () { return null; });\n    }\n    function abfragen(url) {\n        return tokenHolen().then(function (token) {\n            return fetch(ENDPUNKT, { method: 'POST', headers: { 'Content-Type': 'application\/json' }, body: JSON.stringify({ url: url, token: token || '' }) })\n                .then(function (r) { return r.json().then(function (j) { return j; }, function () { return { fehler: 'antwort' }; }); }, function () { return { fehler: 'netz' }; });\n        });\n    }\n\n    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.CP = { bewerten: bewerten, darstellen: null, text: text, kb: kb, ENDPUNKT: ENDPUNKT, STUFEN: STUFEN, VARIANTEN: VARIANTEN, KLASSEN: KLASSEN, T: T };\n\n    var btn = document.getElementById('cp-btn');\n    var out = document.getElementById('cp-ausgabe');\n    if (!btn || !out) { return; }\n\n    function el(tag, stil, txt) { var e = document.createElement(tag); if (stil) { e.setAttribute('style', stil); } if (txt !== undefined &#038;&#038; txt !== null) { e.textContent = txt; } return e; }\n    function wert(id) { var e = document.getElementById(id); return e ? e.value : ''; }\n    var UEBERSCHRIFT = 'font-family: \"Nunito Sans\", sans-serif; font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 22px 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 KASTEN = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 8px; padding: 14px 16px; margin: 0 0 10px;';\n    var GUT = ' color: #7ee787;', WARN = ' color: #ffa94d;', ROT = ' color: #ff7b72;', GRAU = ' color: #8a8a99;';\n    var FARBEN = { hoch: '#ff7b72', mittel: '#ffa94d', niedrig: '#e3b341', info: '#8a8a99', gut: '#7ee787' };\n    var URTEIL = { gut: GUT, warnung: WARN, kritisch: ROT };\n    function gitter(sp) { return el('div', 'display: grid; grid-template-columns: ' + sp + '; gap: 0 18px; align-items: baseline;'); }\n    function paar(g, n, w, stil) { g.appendChild(el('div', ZELLE, n)); g.appendChild(el('div', ZELLE_WERT + (stil || ''), w)); }\n    function ms(v) { return v === null ? '-' : v + ' ms'; }\n\n    function balken(prozent) {\n        var h = el('div', 'height: 8px; background: var(--border, #2a2a35); border-radius: 4px; width: 140px; overflow: hidden; display: inline-block; vertical-align: middle; margin-right: 8px;');\n        var f = el('div', 'height: 100%; width: ' + Math.max(1, Math.min(100, prozent)) + '%; background: ' + (prozent < 40 ? '#7ee787' : (prozent < 80 ? '#e3b341' : '#ffa94d')) + ';');\n        h.appendChild(f);\n        return h;\n    }\n\n    function darstellen(b, ziel) {\n        ziel.innerHTML = '';\n        if (b.fehler) {\n            var txt = T['fehler_' + b.fehler] || T.fehler_unbekannt;\n            if (b.grund &#038;&#038; T['grund_' + b.grund]) { txt = txt + ' ' + T['grund_' + b.grund]; }\n            if (b.limit !== null) { txt = txt.replace('{limit}', String(b.limit)); }\n            ziel.appendChild(el('p', ZELLE + WARN + ' margin: 0;', txt));\n            return;\n        }\n        ziel.appendChild(el('div', 'font-size: 1.05rem; font-weight: 700; margin: 0 0 12px;' + URTEIL[b.urteil], T['urteil_' + b.urteil]));\n\n        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_antwort));\n        var g = gitter('auto auto');\n        paar(g, T.zeile_url, b.url);\n        paar(g, T.zeile_ip, b.ips.length ? b.ips.join(', ') : b.ip, GRAU);\n        if (b.server) { paar(g, T.zeile_server, b.server, GRAU); }\n        paar(g, T.zeile_typ, (b.contentType || '-') + ' (' + T['klasse_' + b.klasse] + ')', b.klasse === 'text' ? '' : GRAU);\n        paar(g, T.zeile_basis, kb(b.basis) + (b.basis ? ' (' + b.basis + ' B)' : ''));\n        if (b.dauer !== null) { paar(g, T.zeile_dauer, ms(b.dauer), GRAU); }\n        if (b.limitRest !== null) { paar(g, T.zeile_limit, String(b.limitRest), GRAU); }\n        ziel.appendChild(g);\n\n        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_varianten));\n        var huelle = el('div', 'overflow-x: auto;');\n        var gp = gitter('auto auto auto auto auto auto auto');\n        [T.spalte_accept, T.spalte_kodierung, T.spalte_leitung, T.spalte_anteil, T.spalte_status, T.spalte_ttfb, T.spalte_gesamt].forEach(function (s) { gp.appendChild(el('div', ZELLE + ' font-weight: 700; color: var(--text-primary, #e8e8ee); white-space: nowrap;', s)); });\n        VARIANTEN.forEach(function (v) {\n            var r = b.abrufe[v];\n            gp.appendChild(el('div', ZELLE_WERT + ' white-space: nowrap;', r.accept || T['variante_' + v]));\n            if (r.ok) {\n                var kod = r.kodierung || 'identity';\n                gp.appendChild(el('div', ZELLE_WERT + (kod === 'identity' ? GRAU : GUT), kod));\n                gp.appendChild(el('div', ZELLE_WERT, kb(r.leitung) + (r.gekappt ? ' ' + T.gekappt_kurz : '')));\n                var z = el('div', ZELLE_WERT + ' white-space: nowrap;');\n                if (r.prozent !== null) { z.appendChild(balken(r.prozent)); z.appendChild(document.createTextNode(r.prozent + ' %')); } else { z.textContent = '-'; }\n                gp.appendChild(z);\n                gp.appendChild(el('div', ZELLE_WERT + GRAU, r.status === null ? '-' : String(r.status)));\n                gp.appendChild(el('div', ZELLE_WERT + GRAU, ms(r.ttfb)));\n                gp.appendChild(el('div', ZELLE_WERT + GRAU, ms(r.gesamt)));\n            } else {\n                gp.appendChild(el('div', ZELLE_WERT + ROT + ' grid-column: span 6; white-space: normal;', T.fehlgeschlagen + (r.fehler ? ' (' + r.fehler + ')' : '')));\n            }\n        });\n        huelle.appendChild(gp);\n        ziel.appendChild(huelle);\n\n        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_befunde));\n        var irgendwas = false;\n        STUFEN.forEach(function (s) {\n            var gr = b.gruppen[s];\n            if (!gr.length) { return; }\n            irgendwas = true;\n            ziel.appendChild(el('div', 'font-weight: 700; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.5px; margin: 14px 0 6px; color: ' + FARBEN[s] + ';', T['stufe_' + s] + ' (' + gr.length + ')'));\n            gr.forEach(function (f) {\n                var k = el('div', KASTEN + ' border-left: 3px solid ' + FARBEN[s] + ';');\n                var t = text('befund_' + f.key, f.daten) || f.key;\n                var teile = t.split(' || ');\n                k.appendChild(el('div', 'color: var(--text-primary, #e8e8ee); font-size: 0.9rem; font-weight: 700;', teile[0]));\n                if (teile[1]) { k.appendChild(el('div', ZELLE + ' padding: 6px 0 0; line-height: 1.55;', teile[1])); }\n                ziel.appendChild(k);\n            });\n        });\n        if (!irgendwas) { ziel.appendChild(el('p', ZELLE + ' margin: 0;', T.keine_befunde)); }\n    }\n    window.LW_TEST.CP.darstellen = darstellen;\n\n    var laeuft = false;\n    btn.addEventListener('click', function () {\n        if (laeuft) { return; }\n        laeuft = true; btn.disabled = true;\n        out.innerHTML = '';\n        out.appendChild(el('p', ZELLE + GRAU + ' margin: 0;', T.laeuft));\n        abfragen(wert('cp-url')).then(function (a) { darstellen(bewerten(a), out); laeuft = false; btn.disabled = false; },\n            function () { darstellen(bewerten({ fehler: 'netz' }), out); laeuft = false; btn.disabled = false; });\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ruft eine Adresse f\u00fcnfmal mit verschiedenen Accept-Encoding-Werten ab und zeigt, was der Server wirklich sendet: welche Kodierungen er anbietet, wie viele Bytes je Variante \u00fcber die Leitung gehen, was der kombinierte Browser-Header bekommt und ob Vary und ETag die Caches auseinanderhalten.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9283,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[92214,92301,92292],"class_list":["post-15550","page","type-page","status-publish","hentry","tag-devops-de","tag-networking-de","tag-web-performance-de"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd - 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\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Ruft eine Adresse f\u00fcnfmal mit verschiedenen Accept-Encoding-Werten ab und zeigt, was der Server wirklich sendet: welche Kodierungen er anbietet, wie viele Bytes je Variante \u00fcber die Leitung gehen, was der kombinierte Browser-Header bekommt und ob Vary und ETag die Caches auseinanderhalten.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\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\\\/de\\\/werkzeuge\\\/compression-negotiation-checker-gzip-brotli-zstd\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/compression-negotiation-checker-gzip-brotli-zstd\\\/\",\"name\":\"Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-05T11:30:58+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/compression-negotiation-checker-gzip-brotli-zstd\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/compression-negotiation-checker-gzip-brotli-zstd\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/compression-negotiation-checker-gzip-brotli-zstd\\\/#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\\\/toolbox-2\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd\"}]},{\"@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":"Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd - 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\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/","og_locale":"en_US","og_type":"article","og_title":"Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd - Lukas Wojcik - Blog","og_description":"Ruft eine Adresse f\u00fcnfmal mit verschiedenen Accept-Encoding-Werten ab und zeigt, was der Server wirklich sendet: welche Kodierungen er anbietet, wie viele Bytes je Variante \u00fcber die Leitung gehen, was der kombinierte Browser-Header bekommt und ob Vary und ETag die Caches auseinanderhalten.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/","og_site_name":"Lukas Wojcik - Blog","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\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/","url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/","name":"Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-05T11:30:58+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/compression-negotiation-checker-gzip-brotli-zstd\/#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\/toolbox-2\/"},{"@type":"ListItem","position":3,"name":"Kompressions-Aushandlungs-Checker: gzip, Brotli, zstd"}]},{"@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\/15550","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=15550"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/15550\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9283"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=15550"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=15550"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}