{"id":15553,"date":"2026-09-05T13:43:43","date_gmt":"2026-09-05T11:43:43","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/werkzeuge\/cache-control-revalidation-analyzer\/"},"modified":"2026-09-05T13:43:43","modified_gmt":"2026-09-05T11:43:43","slug":"cache-control-revalidation-analyzer","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/cache-control-revalidation-analyzer\/","title":{"rendered":"Cache-Control- und Revalidierungs-Analyzer"},"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;\">Cache-Control ist eine kurze Kopfzeile mit einer langen Liste von Missverst\u00e4ndnissen: no-cache hei\u00dft nicht \u201enicht speichern\u201c, max-age=0 ist kein no-store, s-maxage spricht nur zu geteilten Caches, und ohne all das erfindet ein Browser eine Lebensdauer aus Last-Modified. Diese Pr\u00fcfung ruft eine Adresse von diesem Server ab, rechnet die Frischedauer f\u00fcr einen Browser und f\u00fcr einen geteilten Cache so, wie RFC 9111 es tut, schickt dann eine Anfrage mit If-None-Match und eine mit If-Modified-Since, um zu sehen, ob die Validatoren wirklich funktionieren, und eine zweite normale Anfrage, um zu lesen, was ein Cache davor beim zweiten Mal tut.<\/p>\n<div style=\"margin-bottom: 14px;\">\n        <label for=\"cc-url\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Adresse (eine Seite, ein Stylesheet, ein Skript, ein Bild)<\/label><br \/>\n        <input id=\"cc-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 bis zu vier Anfragen von je h\u00f6chstens 256 KB 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=\"cc-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;\">Cache-Kopfzeilen analysieren<\/button><\/p>\n<div id=\"cc-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 antwortet je Standort, der Cache-Status von hier kann anderswo abweichen; die zweite Anfrage folgt der ersten binnen Sekunden, was ein Cache mit Mindest-TTL anders behandeln kann als echten Verkehr; Kopfzeilen, die JavaScript oder Service Worker setzen, sind unsichtbar; und die heuristische Lebensdauer ist der Vorschlag des RFC von zehn Prozent, einzelne Browser haben eigene Regeln.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Cache-Control ist eine kurze Kopfzeile mit einer langen Liste von Missverst\u00e4ndnissen: no-cache hei\u00dft nicht \u201enicht speichern\u201c, max-age=0 ist kein no-store, s-maxage spricht nur zu geteilten Caches, und ohne all das erfindet ein Browser eine Lebensdauer aus Last-Modified. Diese Pr\u00fcfung ruft eine Adresse von diesem Server ab, rechnet die Frischedauer f\u00fcr einen Browser und f\u00fcr einen geteilten Cache so, wie RFC 9111 es tut, schickt dann eine Anfrage mit If-None-Match und eine mit If-Modified-Since, um zu sehen, ob die Validatoren wirklich funktionieren, und eine zweite normale Anfrage, um zu lesen, was ein Cache davor beim zweiten Mal tut.\",\"label_url\":\"Adresse (eine Seite, ein Stylesheet, ein Skript, ein Bild)\",\"datenschutz\":\"Von diesem Server gehen Weiterleitungen und bis zu vier Anfragen von je h\u00f6chstens 256 KB 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\":\"Cache-Kopfzeilen analysieren\",\"laeuft\":\"Abrufen, dann revalidieren...\",\"grenze\":\"Grenzen, die dazugeh\u00f6ren: Gepr\u00fcft wird nur eine der aufgel\u00f6sten Adressen; ein CDN antwortet je Standort, der Cache-Status von hier kann anderswo abweichen; die zweite Anfrage folgt der ersten binnen Sekunden, was ein Cache mit Mindest-TTL anders behandeln kann als echten Verkehr; Kopfzeilen, die JavaScript oder Service Worker setzen, sind unsichtbar; und die heuristische Lebensdauer ist der Vorschlag des RFC von zehn Prozent, einzelne Browser haben eigene Regeln.\",\"h_verhalten\":\"Was ein Cache damit macht\",\"zeile_url\":\"Gemessene Adresse\",\"zeile_ip\":\"Aufgel\u00f6ste Adressen\",\"zeile_klasse\":\"Ressource\",\"zeile_verhalten\":\"Verhalten im Browser\",\"zeile_browser\":\"Frisch im Browser f\u00fcr\",\"zeile_geteilt\":\"Frisch im geteilten Cache f\u00fcr\",\"zeile_dauer\":\"Dauer\",\"zeile_limit\":\"Pr\u00fcfungen in dieser Stunde noch\",\"versioniert_zusatz\":\"(versionierter Dateiname)\",\"klasse_html\":\"HTML-Dokument\",\"klasse_asset\":\"Stylesheet oder Skript\",\"klasse_bild\":\"Bild\",\"klasse_schrift\":\"Schrift\",\"klasse_daten\":\"Daten (JSON, XML, Text)\",\"klasse_sonstiges\":\"Sonstiges\",\"verhalten_nicht_gespeichert\":\"Wird gar nicht gespeichert: Jeder Besuch l\u00e4dt die Antwort neu.\",\"verhalten_heuristisch\":\"Keine Lebensdauer und kein Validator: Der Browser r\u00e4t eine Lebensdauer aus Last-Modified und beh\u00e4lt ohne dieses nichts.\",\"verhalten_heuristisch_oder_revalidiert\":\"Keine ausdr\u00fcckliche Lebensdauer: Der Browser r\u00e4t eine aus Last-Modified und revalidiert danach.\",\"verhalten_immer_revalidiert\":\"Gespeichert, aber jede Nutzung fragt erst den Server; unver\u00e4nderter Inhalt kommt als kurzes 304 zur\u00fcck.\",\"verhalten_immer_neu\":\"Gespeichert, aber jede Nutzung fragt erst den Server, und ohne Validator muss der Server alles erneut senden.\",\"verhalten_unveraenderlich\":\"F\u00fcr die ganze Lebensdauer gespeichert und nie revalidiert, auch nicht beim Neuladen.\",\"verhalten_frisch_dann_revalidiert\":\"W\u00e4hrend der Lebensdauer aus dem Cache, danach mit einer bedingten Anfrage revalidiert.\",\"verhalten_frisch_dann_neu\":\"W\u00e4hrend der Lebensdauer aus dem Cache, danach vollst\u00e4ndig neu geladen, weil ein Validator fehlt.\",\"verhalten_unbekannt\":\"Nicht bestimmbar, die Adresse lie\u00df sich nicht abrufen.\",\"quelle_no_store\":\"no-store, nie gespeichert\",\"quelle_private\":\"private, nicht f\u00fcr geteilte Caches\",\"quelle_s_maxage\":\"aus s-maxage\",\"quelle_max_age\":\"aus max-age\",\"quelle_expires\":\"aus Expires\",\"quelle_expires_unlesbar\":\"Expires unlesbar, gilt als abgelaufen\",\"quelle_heuristisch\":\"heuristisch, 10 % des Alters seit Last-Modified\",\"quelle_keine\":\"keine Angabe\",\"h_kopf\":\"Cache-Kopfzeilen, wie gesendet\",\"h_abrufe\":\"Anfragen\",\"spalte_abruf\":\"Anfrage\",\"spalte_status\":\"Status\",\"spalte_bytes\":\"Bytes\",\"spalte_ttfb\":\"Erstes Byte\",\"spalte_age\":\"Age\",\"spalte_cache\":\"Cache-Status\",\"abruf_erster\":\"Normales GET\",\"abruf_inm\":\"Mit If-None-Match (ETag)\",\"abruf_ims\":\"Mit If-Modified-Since\",\"abruf_zweiter\":\"Normales GET, zweites Mal\",\"abruf_entfaellt\":\"nicht gesendet, die erste Antwort trug daf\u00fcr keinen Validator\",\"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\":\"Lebensdauer und Revalidierung passen zu dieser Art Ressource.\",\"urteil_warnung\":\"Caching funktioniert im Grundsatz, mit etwas, das Downloads kostet oder Caches verwirrt.\",\"urteil_kritisch\":\"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 Analyse bezieht sich auf die Endadresse der Kette.\",\"befund_abruf_fehlgeschlagen\":\"Die Adresse antwortet nicht || {fehler}\",\"befund_status_fehler\":\"Der Server hat mit Status {status} geantwortet || Analysiert werden die Cache-Kopfzeilen einer Fehlerantwort, nicht die der gemeinten Ressource. Fehlerantworten werden selten gecacht, und 404 nur, wenn sie es ausdr\u00fccklich erlauben.\",\"befund_heuristisch\":\"Kein Cache-Control, kein Expires: Lebensdauer aus Last-Modified geraten ({dauer}) || Ohne ausdr\u00fcckliche Lebensdauer darf ein Cache eine Heuristik anwenden; RFC 9111 schl\u00e4gt zehn Prozent der Zeit seit Last-Modified vor ({lm}). Damit w\u00e4chst die Lebensdauer mit dem Alter der Datei und unterscheidet sich je Browser. Ein ausdr\u00fcckliches max-age ersetzt das Raten.\",\"befund_kein_cache_control\":\"Kein Cache-Control und kein Expires || Nichts sagt, wie lange die Antwort wiederverwendet werden darf, und ohne Last-Modified kann ein Cache nicht einmal raten. Browser revalidieren oder laden dann jedes Mal neu. Ein zur Ressource passendes max-age ist die Abhilfe.\",\"befund_no_store\":\"no-store || Die Antwort darf in keinen Cache geschrieben werden. Richtig f\u00fcr pers\u00f6nliche oder sensible Inhalte, verschwenderisch f\u00fcr alles Statische: Jeder Besuch l\u00e4dt neu, und auch der Zur\u00fcck-Knopf l\u00e4dt nach.\",\"befund_no_cache\":\"no-cache || Oft missverstanden: Die Antwort darf gespeichert werden, aber jede Wiederverwendung muss erst beim Server nachfragen. Mit Validator ist das ein g\u00fcnstiges 304, ohne ein voller Download. Wer das Speichern verbieten will, braucht no-store.\",\"befund_no_store_und_no_cache\":\"no-store zusammen mit no-cache || no-store verbietet das Speichern bereits; no-cache obendrauf ist \u00fcberfl\u00fcssig. Harmlos, aber es deutet darauf hin, dass die Direktiven kopiert und nicht gew\u00e4hlt wurden.\",\"befund_max_age_null\":\"max-age=0 || Null Sekunden frisch, also revalidiert jede Wiederverwendung. Anders als bei no-store bleibt die Antwort gespeichert und kann mit einem 304 best\u00e4tigt werden ({revalidate}). Das ist die klassische Einstellung f\u00fcr HTML, das immer aktuell sein muss, sich aber meist nicht \u00e4ndert.\",\"befund_private\":\"private || Nur der Browser darf die Antwort speichern; geteilte Caches und CDNs nicht. Richtig f\u00fcr personalisierte Seiten, eine vertane Gelegenheit bei \u00f6ffentlichen.\",\"befund_public_ohne_dauer\":\"public ohne Lebensdauer || public erlaubt geteilten Caches das Speichern, selbst einer Antwort, die sonst privat w\u00e4re, sagt aber nichts \u00fcber die Dauer. Allein tut es selten, was gemeint war.\",\"befund_s_maxage\":\"s-maxage {dauer} f\u00fcr geteilte Caches, {browser} f\u00fcr Browser || Geteilte Caches wie ein CDN nutzen s-maxage und ignorieren max-age; Browser ignorieren s-maxage. Zwei Lebensdauern f\u00fcr zwei Adressaten, genau der Zweck der Direktive.\",\"befund_immutable_kurz\":\"immutable mit kurzer Lebensdauer ({dauer}) || immutable sagt dem Browser, auch beim Neuladen nicht zu revalidieren. Das ergibt nur mit langer Lebensdauer und versioniertem Dateinamen Sinn; mit kurzer spart es fast nichts.\",\"befund_immutable_ohne_version\":\"immutable auf einem Dateinamen ohne Version || Der Browser revalidiert w\u00e4hrend der Lebensdauer nicht, auch nicht beim Neuladen. \u00c4ndert sich die Datei unter gleichem Namen, behalten Besucher die alte bis zum Ablauf. immutable geh\u00f6rt auf gehashte oder versionierte Dateinamen.\",\"befund_immutable_ok\":\"immutable mit {dauer} auf versioniertem Dateinamen || Der Browser beh\u00e4lt die Datei die ganze Lebensdauer und l\u00e4sst beim Neuladen die bedingte Anfrage weg. So ist es gemeint.\",\"befund_swr\":\"stale-while-revalidate {dauer} || Nach Ablauf darf der Cache die veraltete Kopie so lange ausliefern, w\u00e4hrend er im Hintergrund eine frische holt. Besucher warten nie auf die Revalidierung.\",\"befund_sie\":\"stale-if-error {dauer} || F\u00e4llt der Ursprung aus, darf der Cache die veraltete Kopie so lange weiter ausliefern. Ein stilles Sicherheitsnetz bei St\u00f6rungen.\",\"befund_must_revalidate\":\"must-revalidate bei einer Lebensdauer von {dauer} || Einmal veraltet, darf die Antwort nicht ohne erfolgreiche Revalidierung ausgeliefert werden, auch nicht bei unerreichbarem Ursprung. Es verk\u00fcrzt die Lebensdauer nicht; es verbietet nur das Ausliefern veralteter Kopien.\",\"befund_pragma\":\"Pragma: no-cache || Ein Relikt aus HTTP\\\/1.0. Als Antwortkopfzeile hat es keine festgelegte Bedeutung; Caches folgen Cache-Control. Harmlos, aber wirkungslos.\",\"befund_direktive_unbekannt\":\"Unbekannte Direktiven: {liste} || Caches ignorieren Direktiven, die sie nicht kennen. Ein Tippfehler hier schaltet still ab, was gemeint war.\",\"befund_expires_widerspruch\":\"Expires ({expires}) widerspricht max-age ({maxage}) || Sind beide vorhanden, gewinnt max-age, und Expires wird ignoriert. Ein Widerspruch hei\u00dft meist, dass zwei Schichten sie unabh\u00e4ngig setzen; der Expires-Wert ist totes Gewicht.\",\"befund_expires_unlesbar\":\"Expires ist kein g\u00fcltiges Datum ({wert}) || Ein unlesbares Expires gilt als bereits abgelaufen. Werte wie 0 oder -1 sind eine verbreitete Art, das zu sagen, aber eine Cache-Control-Direktive sagt es klarer.\",\"befund_expires_vergangen\":\"Expires liegt in der Vergangenheit || Die Antwort ist bei Ankunft veraltet und wird bei jeder Nutzung revalidiert oder neu geladen. Ohne max-age ist das die einzige Angabe zur Lebensdauer.\",\"befund_expires_allein\":\"Lebensdauer nur aus Expires ({dauer}) || Funktioniert, aber Expires ist eine absolute Zeit und h\u00e4ngt davon ab, dass die Uhren von Server und Client \u00fcbereinstimmen. max-age ist relativ und davon unabh\u00e4ngig.\",\"befund_date_abweichung\":\"Die Serveruhr weicht um {sekunden} s von der dieses Servers ab || Expires- und Age-Rechnungen h\u00e4ngen an der Date-Kopfzeile. Eine abweichende Serveruhr verk\u00fcrzt oder verl\u00e4ngert jede aus absoluten Zeiten berechnete Lebensdauer.\",\"befund_date_fehlt\":\"Keine Date-Kopfzeile || Ursprungsserver m\u00fcssen eine senden. Ohne sie nehmen Caches ihre eigene Uhr, und Expires l\u00e4sst sich nicht verl\u00e4sslich deuten.\",\"befund_validator_fehlt\":\"Kein ETag und kein Last-Modified || Nach Ablauf der Lebensdauer kann der Browser nicht fragen, ob sich der Inhalt ge\u00e4ndert hat; er muss alles neu laden. Ein Last-Modified oder ein ETag macht daraus ein 304 ohne Inhalt.\",\"befund_etag_schwach\":\"Schwacher ETag ({etag}) || W\\\/ kennzeichnet einen Validator, der semantische, nicht byteweise Gleichheit verspricht. F\u00fcr die Revalidierung in Ordnung; f\u00fcr Bereichsanfragen nicht nutzbar.\",\"befund_last_modified_unlesbar\":\"Last-Modified ist kein g\u00fcltiges Datum ({wert}) || Clients ignorieren einen unlesbaren Validator, bedingte Anfragen darauf finden also nie statt.\",\"befund_last_modified_zukunft\":\"Last-Modified liegt in der Zukunft ({wert}) || Ein \u00c4nderungszeitpunkt nach jetzt deutet auf eine falsche Serveruhr. Caches behandeln ihn wie die aktuelle Zeit; darauf gest\u00fctzte Heuristiken brechen zusammen.\",\"befund_etag_304\":\"If-None-Match hat 304 geliefert || Der ETag funktioniert: Eine unver\u00e4nderte Ressource kostet ein paar Kopfzeilenbytes statt {bytes} Bytes.\",\"befund_etag_kein_304\":\"If-None-Match hat 200 geliefert, kein 304 || Der Server hat einen ETag gesendet ({etag}), ihn in der bedingten Anfrage aber nicht erkannt; der ganze Inhalt kam erneut. Apache mit mod_deflate ist eine klassische Ursache: Es h\u00e4ngt -gzip an den ETag und erkennt danach das eigene Suffix nicht (DeflateAlterETag). CDNs, die ETags umschreiben, tun dasselbe.\",\"befund_etag_status\":\"If-None-Match hat {status} geliefert || Weder 200 noch 304; die bedingte Anfrage wurde als etwas anderes behandelt.\",\"befund_ims_304\":\"If-Modified-Since hat 304 geliefert || Der datumsbasierte Validator funktioniert.\",\"befund_ims_kein_304\":\"If-Modified-Since hat 200 geliefert, kein 304 || Der Server sendet Last-Modified, beachtet es in einer bedingten Anfrage aber nicht. Mit funktionierendem ETag kostet das nichts; ohne ist jede Revalidierung ein voller Download.\",\"befund_304_mit_inhalt\":\"304 mit einem Inhalt von {bytes} Bytes || Ein 304 darf keinen Inhalt tragen. Clients ignorieren ihn, die Bytes werden trotzdem \u00fcbertragen, und manche Zwischenstationen verschlucken sich daran.\",\"befund_etag_wechselt\":\"Der ETag wechselt zwischen zwei gleichen Anfragen || Die erste Antwort trug {a}, die bedingte {b}. Ein Validator, der sich bei jeder Anfrage \u00e4ndert, passt nie, bedingte Anfragen scheitern also immer. Typische Ursachen: ein ETag aus einem Zeitstempel oder aus einem Token je Anfrage.\",\"befund_vary_stern\":\"Vary: * || Die Antwort h\u00e4ngt von etwas au\u00dferhalb der Anfragekopfzeilen ab; Caches m\u00fcssen jede Anfrage als verschieden behandeln. F\u00fcr geteilte Caches praktisch nicht speicherbar.\",\"befund_vary_user_agent\":\"Vary: User-Agent || Bei Tausenden verschiedener User-Agent-Zeichenketten h\u00e4lt ein geteilter Cache je Zeichenkette eine Kopie und trifft fast nie. Client Hints oder gar kein Vary erf\u00fcllen denselben Zweck ohne die Zersplitterung.\",\"befund_vary_cookie\":\"Vary: Cookie || Jeder verschiedene Cookie-Wert bekommt einen eigenen Cache-Eintrag. Setzt die Seite au\u00dferdem ein Cookie je Besucher, trifft der Cache f\u00fcr einen zweiten Besucher nie.\",\"befund_set_cookie_geteilt\":\"Set-Cookie auf einer Antwort, die geteilte Caches {dauer} behalten d\u00fcrfen || Ein Cache, der diese Antwort speichert, speichert das Cookie mit und gibt das Cookie eines Besuchers an den n\u00e4chsten weiter. Die meisten CDNs cachen Antworten mit Set-Cookie deshalb gar nicht, das gemeinte s-maxage findet also auch nicht statt. Entweder das Cookie weglassen oder die Antwort als private markieren.\",\"befund_cache_davor\":\"Vor dem Ursprung sitzt ein Cache ({system}) || Erste Anfrage: {status1}, Age {age1}; zweite Anfrage: {status2}, Age {age2}. Age z\u00e4hlt die Sekunden, die die Kopie im Cache liegt.\",\"befund_cache_trifft\":\"Der Cache davor trifft ({status}) || Die Antwort kam aus dem Cache, nicht vom Ursprung. Besucher bekommen sie, ohne dass der Ursprung arbeitet.\",\"befund_cache_trifft_nicht\":\"Der Cache davor speichert das nicht ({status}) || Beide Anfragen gingen zum Ursprung. F\u00fcr HTML hinter einem CDN ist das die \u00fcbliche Vorgabe; statische Dateien sollten treffen.\",\"befund_age_ueber_frische\":\"Age {age} s \u00fcbersteigt die Lebensdauer von {frische} s || Der Cache hat eine Kopie ausgeliefert, die nach ihren eigenen Kopfzeilen schon veraltet ist. Entweder wendet der Cache eigene Regeln an, oder stale-while-revalidate ist am Werk.\",\"befund_html_lang\":\"HTML {dauer} ohne Revalidierung gecacht || Besucher sehen nach einer \u00c4nderung so lange eine veraltete Seite, und eine Korrektur l\u00e4sst sich nicht zu ihnen durchdr\u00fccken. Ein kurzes max-age mit must-revalidate oder max-age=0 mit Validator h\u00e4lt HTML zu geringen Kosten aktuell.\",\"befund_html_kurz\":\"HTML {dauer} frisch, danach revalidiert || Eine kurze Lebensdauer f\u00e4ngt Sch\u00fcbe wiederholter Anfragen ab, w\u00e4hrend \u00c4nderungen die Besucher schnell erreichen.\",\"befund_html_revalidiert\":\"HTML wird bei jeder Nutzung revalidiert || Der Browser beh\u00e4lt eine Kopie und fragt jedes Mal beim Server; unver\u00e4nderte Seiten kommen als 304 zur\u00fcck. \u00c4nderungen erreichen Besucher sofort.\",\"befund_asset_lang_versioniert\":\"Versionierte Datei {dauer} gecacht || Eine lange Lebensdauer auf einem Dateinamen, der sich mit dem Inhalt \u00e4ndert, ist der Idealfall: ein Jahr gecacht, ersetzt in dem Moment, in dem das HTML einen neuen Namen nennt.\",\"befund_asset_lang_unversioniert\":\"Lange Lebensdauer ({dauer}) auf einem unversionierten Dateinamen || Eine \u00c4nderung unter gleichem Namen erreicht wiederkehrende Besucher erst, wenn die Kopie abl\u00e4uft. Entweder Hash oder Version in den Namen, oder die Lebensdauer k\u00fcrzen.\",\"befund_asset_kurz\":\"Kurze Lebensdauer f\u00fcr eine statische Datei ({dauer}) || Stylesheets, Skripte, Bilder und Schriften \u00e4ndern sich selten; eine Lebensdauer unter einem Tag hei\u00dft h\u00e4ufige Revalidierung ohne Nutzen. Mit versioniertem Namen ist ein Jahr \u00fcblich.\",\"befund_asset_mittel\":\"Datei {dauer} gecacht || Ein Mittelweg: weniger Revalidierung als bei kurzer Lebensdauer, weiterhin begrenzte Gefahr veralteter Kopien.\",\"befund_asset_ungecached\":\"Statische Datei nicht gecacht ({quelle}) || Jeder Seitenaufruf l\u00e4dt diese Datei erneut. Ein max-age, am besten mit versioniertem Namen, beseitigt diese Downloads vollst\u00e4ndig.\",\"befund_versioniert_aber_kurz\":\"Versionierter Dateiname, aber nur {dauer} Lebensdauer || Der Name \u00e4ndert sich bereits mit dem Inhalt, eine lange Lebensdauer tr\u00e4gt also kein Risiko. Die kurze verschenkt den Nutzen der Versionierung.\"};<\/p>\n<p>    var ENDPUNKT = '\/lw-cachecheck.php';\n    var SITEKEY = '6LcrPkEtAAAAAPo1QCOf-IIM2fCL0UfdJz4y2iSY';\n    var STUFEN = ['hoch', 'mittel', 'niedrig', 'info', 'gut'];\n    var ABRUFE = ['erster', 'inm', 'ims', 'zweiter'];\n    var KLASSEN = ['html', 'asset', 'bild', 'schrift', 'daten', 'sonstiges'];\n    var VERHALTEN = ['nicht_gespeichert', 'heuristisch', 'heuristisch_oder_revalidiert', 'immer_revalidiert', 'immer_neu', 'unveraenderlich', 'frisch_dann_revalidiert', 'frisch_dann_neu', 'unbekannt'];\n    var QUELLEN = ['no-store', 'private', 's-maxage', 'max-age', 'expires', 'expires-unlesbar', 'heuristisch', 'keine'];\n    var KOPF_REIHE = ['cache-control', 'expires', 'date', 'last-modified', 'etag', 'age', 'vary', 'pragma', 'surrogate-control', 'cdn-cache-control', 'cloudflare-cdn-cache-control', 'cf-cache-status', 'x-cache', 'x-cache-hits', 'x-cache-enabled', 'x-served-by', 'via', 'x-varnish', 'x-litespeed-cache', 'x-nginx-cache', 'x-proxy-cache', 'x-drupal-cache', 'x-cache-status', 'set-cookie', 'content-type', 'server'];<\/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 quelleText(q) { var t = T['quelle_' + String(q || 'keine').replace(\/-\/g, '_')]; return typeof t === 'string' ? t : String(q); }<\/p>\n<p>    function abruf(r) {\n        if (!r || typeof r !== 'object') { return null; }\n        return { ok: !!r.ok, status: zahl(r.status), fehler: r.fehler ? String(r.fehler) : null, bytes: zahl(r.bytes), ttfb: zahl(r.ttfb_ms), gesamt: zahl(r.gesamt_ms), age: zahl(r.age), cacheStatus: r.cache_status ? String(r.cache_status) : null };\n    }\n    function frische(f) {\n        f = (f && typeof f === 'object') ? f : {};\n        return { sekunden: zahl(f.sekunden), quelle: QUELLEN.indexOf(f.quelle) === -1 ? 'keine' : f.quelle, text: f.text ? String(f.text) : '-' };\n    }<\/p>\n<p>    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 && 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        ABRUFE.forEach(function (v) { abrufe[v] = abruf(a.abrufe ? a.abrufe[v] : null); });\n        var kopf = {};\n        if (a.kopf && typeof a.kopf === 'object') { Object.keys(a.kopf).forEach(function (k) { if (typeof a.kopf[k] === 'string') { kopf[k.toLowerCase()] = a.kopf[k]; } }); }\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),\n            urteil: (a.urteil === 'gut' || a.urteil === 'warnung' || a.urteil === 'kritisch') ? a.urteil : 'kritisch',\n            klasse: KLASSEN.indexOf(a.klasse) === -1 ? 'sonstiges' : a.klasse, versioniert: !!a.versioniert,\n            verhalten: VERHALTEN.indexOf(a.verhalten) === -1 ? 'unbekannt' : a.verhalten,\n            browser: frische(a.browser), geteilt: frische(a.geteilt),\n            direktiven: (a.direktiven && typeof a.direktiven === 'object') ? Object.keys(a.direktiven) : [],\n            kopf: kopf, abrufe: abrufe, befunde: befunde, gruppen: gruppen,\n            kette: liste(a.kette), dauer: zahl(a.dauer_ms), limitRest: zahl(a.limit_rest)\n        };\n    }<\/p>\n<p>    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: 'cachecheck' }).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    }<\/p>\n<p>    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.CC = { bewerten: bewerten, darstellen: null, text: text, quelleText: quelleText, ENDPUNKT: ENDPUNKT, STUFEN: STUFEN, ABRUFE: ABRUFE, KLASSEN: KLASSEN, VERHALTEN: VERHALTEN, QUELLEN: QUELLEN, T: T };<\/p>\n<p>    var btn = document.getElementById('cc-btn');\n    var out = document.getElementById('cc-ausgabe');\n    if (!btn || !out) { return; }<\/p>\n<p>    function el(tag, stil, txt) { var e = document.createElement(tag); if (stil) { e.setAttribute('style', stil); } if (txt !== undefined && 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'; }<\/p>\n<p>    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 && 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]));<\/p>\n<p>        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_verhalten));\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        paar(g, T.zeile_klasse, T['klasse_' + b.klasse] + (b.versioniert ? ' ' + T.versioniert_zusatz : ''), GRAU);\n        paar(g, T.zeile_verhalten, T['verhalten_' + b.verhalten], b.verhalten === 'unveraenderlich' || b.verhalten === 'frisch_dann_revalidiert' || b.verhalten === 'immer_revalidiert' ? GUT : (b.verhalten === 'heuristisch' || b.verhalten === 'immer_neu' ? WARN : ''));\n        paar(g, T.zeile_browser, b.browser.text + '  (' + quelleText(b.browser.quelle) + ')', b.browser.sekunden === null ? WARN : '');\n        paar(g, T.zeile_geteilt, b.geteilt.text + '  (' + quelleText(b.geteilt.quelle) + ')', b.geteilt.sekunden === null ? WARN : '');\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);<\/p>\n<p>        var kopfKeys = KOPF_REIHE.filter(function (k) { return typeof b.kopf[k] === 'string'; });\n        if (kopfKeys.length) {\n            ziel.appendChild(el('div', UEBERSCHRIFT, T.h_kopf));\n            var gk = gitter('auto auto');\n            kopfKeys.forEach(function (k) { paar(gk, k, b.kopf[k], k === 'cache-control' ? '' : GRAU); });\n            ziel.appendChild(gk);\n        }<\/p>\n<p>        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_abrufe));\n        var huelle = el('div', 'overflow-x: auto;');\n        var gp = gitter('auto auto auto auto auto auto');\n        [T.spalte_abruf, T.spalte_status, T.spalte_bytes, T.spalte_ttfb, T.spalte_age, T.spalte_cache].forEach(function (s) { gp.appendChild(el('div', ZELLE + ' font-weight: 700; color: var(--text-primary, #e8e8ee); white-space: nowrap;', s)); });\n        ABRUFE.forEach(function (v) {\n            var r = b.abrufe[v];\n            gp.appendChild(el('div', ZELLE + ' white-space: nowrap;', T['abruf_' + v]));\n            if (r === null) { gp.appendChild(el('div', ZELLE_WERT + GRAU + ' grid-column: span 5;', T.abruf_entfaellt)); return; }\n            if (!r.ok) { gp.appendChild(el('div', ZELLE_WERT + ROT + ' grid-column: span 5; white-space: normal;', T.fehlgeschlagen + (r.fehler ? ' (' + r.fehler + ')' : ''))); return; }\n            gp.appendChild(el('div', ZELLE_WERT + (r.status === 304 ? GUT : ''), String(r.status)));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, r.bytes === null ? '-' : String(r.bytes)));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, ms(r.ttfb)));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, r.age === null ? '-' : String(r.age)));\n            gp.appendChild(el('div', ZELLE_WERT + (r.cacheStatus && \/^(hit|stale|revalidated|updating)\/i.test(r.cacheStatus) ? GUT : GRAU), r.cacheStatus || '-'));\n        });\n        huelle.appendChild(gp);\n        ziel.appendChild(huelle);<\/p>\n<p>        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.CC.darstellen = darstellen;<\/p>\n<p>    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('cc-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>Liest die Cache-Kopfzeilen einer Adresse, rechnet aus, wie lange Browser und geteilte Caches die Antwort behalten d\u00fcrfen und woraus sich das ergibt, schickt bedingte Anfragen, um zu sehen, ob ETag und Last-Modified wirklich ein 304 liefern, und pr\u00fcft, ob ein CDN oder Seitencache davor trifft.<\/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-15553","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>Cache-Control- und Revalidierungs-Analyzer - 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\/cache-control-revalidation-analyzer\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cache-Control- und Revalidierungs-Analyzer - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Liest die Cache-Kopfzeilen einer Adresse, rechnet aus, wie lange Browser und geteilte Caches die Antwort behalten d\u00fcrfen und woraus sich das ergibt, schickt bedingte Anfragen, um zu sehen, ob ETag und Last-Modified wirklich ein 304 liefern, und pr\u00fcft, ob ein CDN oder Seitencache davor trifft.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/cache-control-revalidation-analyzer\/\" \/>\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\\\/cache-control-revalidation-analyzer\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/cache-control-revalidation-analyzer\\\/\",\"name\":\"Cache-Control- und Revalidierungs-Analyzer - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-05T11:43:43+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/cache-control-revalidation-analyzer\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/cache-control-revalidation-analyzer\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/cache-control-revalidation-analyzer\\\/#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\":\"Cache-Control- und Revalidierungs-Analyzer\"}]},{\"@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":"Cache-Control- und Revalidierungs-Analyzer - 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\/cache-control-revalidation-analyzer\/","og_locale":"en_US","og_type":"article","og_title":"Cache-Control- und Revalidierungs-Analyzer - Lukas Wojcik - Blog","og_description":"Liest die Cache-Kopfzeilen einer Adresse, rechnet aus, wie lange Browser und geteilte Caches die Antwort behalten d\u00fcrfen und woraus sich das ergibt, schickt bedingte Anfragen, um zu sehen, ob ETag und Last-Modified wirklich ein 304 liefern, und pr\u00fcft, ob ein CDN oder Seitencache davor trifft.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/cache-control-revalidation-analyzer\/","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\/cache-control-revalidation-analyzer\/","url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/cache-control-revalidation-analyzer\/","name":"Cache-Control- und Revalidierungs-Analyzer - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-05T11:43:43+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/cache-control-revalidation-analyzer\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/cache-control-revalidation-analyzer\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/cache-control-revalidation-analyzer\/#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":"Cache-Control- und Revalidierungs-Analyzer"}]},{"@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\/15553","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=15553"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/15553\/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=15553"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=15553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}