{"id":15564,"date":"2026-09-05T14:29:45","date_gmt":"2026-09-05T12:29:45","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/"},"modified":"2026-09-05T14:29:45","modified_gmt":"2026-09-05T12:29:45","slug":"well-known-policy-files-inspector-security-txt-ads-txt","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/","title":{"rendered":"Well-known &#038; Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt"},"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 domain speaks to machines through a handful of files at fixed paths. security.txt tells researchers where to report a vulnerability, robots.txt and llms.txt address crawlers, ads.txt names who may sell the inventory, gpc.json declares that Global Privacy Control is honoured, change-password sends password managers to the right page, and assetlinks and the Apple app association bind apps to the site. This check fetches all thirteen from this server and judges each by its own specification: a file that exists but has expired, is served as HTML, or answers 200 with the home page instead of a 404, is worth knowing about.<\/p>\n<div style=\"margin-bottom: 14px;\">\n        <label for=\"wk-url\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Domain or address (only the host is used)<\/label><br \/>\n        <input id=\"wk-url\" type=\"text\" value=\"securitytxt.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;\">Thirteen requests of at most 200 KB each go from this server to the host entered, following up to three redirects each. Hosts in private, loopback and link-local networks are refused. The query is protected by reCAPTCHA v3; the calling IP address and the target are stored for one hour to limit the rate.<\/p>\n<p>    <button id=\"wk-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;\">Inspect policy files<\/button><\/p>\n<div id=\"wk-ausgabe\" style=\"margin-top: 22px;\"><\/div>\n<p style=\"color: var(--text-secondary, #a0a0b0); font-size: 0.8rem; margin: 24px 0 0;\">Limits worth knowing: only the fixed paths are checked, not files a site keeps elsewhere; files are cut at 200 KB; a soft 404 is recognised by HTML in the body, which misses servers that answer with a JSON error page; the security.txt signature is detected but not verified; and the absence of most of these files is normal for most sites, so absent counts as information, not as a fault.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"A domain speaks to machines through a handful of files at fixed paths. security.txt tells researchers where to report a vulnerability, robots.txt and llms.txt address crawlers, ads.txt names who may sell the inventory, gpc.json declares that Global Privacy Control is honoured, change-password sends password managers to the right page, and assetlinks and the Apple app association bind apps to the site. This check fetches all thirteen from this server and judges each by its own specification: a file that exists but has expired, is served as HTML, or answers 200 with the home page instead of a 404, is worth knowing about.\",\"label_url\":\"Domain or address (only the host is used)\",\"datenschutz\":\"Thirteen requests of at most 200 KB each go from this server to the host entered, following up to three redirects each. Hosts in private, loopback and link-local networks are refused. The query is protected by reCAPTCHA v3; the calling IP address and the target are stored for one hour to limit the rate.\",\"knopf\":\"Inspect policy files\",\"laeuft\":\"Fetching thirteen files...\",\"grenze\":\"Limits worth knowing: only the fixed paths are checked, not files a site keeps elsewhere; files are cut at 200 KB; a soft 404 is recognised by HTML in the body, which misses servers that answer with a JSON error page; the security.txt signature is detected but not verified; and the absence of most of these files is normal for most sites, so absent counts as information, not as a fault.\",\"zusammenfassung\":\"{basis}: {vorhanden} of {gesamt} files present, {soft} soft 404.\",\"h_dateien\":\"Files\",\"spalte_pfad\":\"Path\",\"spalte_zustand\":\"State\",\"spalte_status\":\"Status\",\"spalte_typ\":\"Content type\",\"spalte_groesse\":\"Size\",\"zustand_vorhanden\":\"present\",\"zustand_fehlt\":\"absent\",\"zustand_soft_404\":\"soft 404 (HTML instead of the file)\",\"zustand_weitergeleitet\":\"redirects\",\"zustand_fehler\":\"not reachable\",\"zustand_status\":\"unexpected status\",\"zustand_leer\":\"empty\",\"zeile_dauer\":\"Took\",\"zeile_limit\":\"Checks left this hour\",\"h_befunde\":\"Findings\",\"stufe_hoch\":\"High\",\"stufe_mittel\":\"Medium\",\"stufe_niedrig\":\"Low\",\"stufe_info\":\"Information\",\"stufe_gut\":\"In order\",\"keine_befunde\":\"Nothing to report.\",\"urteil_gut\":\"The files that exist are consistent; the missing ones are optional.\",\"urteil_warnung\":\"At least one published file is broken or expired, which is worse than not having it.\",\"urteil_kritisch\":\"The host could not be inspected.\",\"fehler_kein_token\":\"The check could not be started because reCAPTCHA did not load.\",\"fehler_captcha\":\"reCAPTCHA classified the request as automated. Reloading the page normally helps.\",\"fehler_zu_viele\":\"The limit of {limit} checks per hour for this address has been reached.\",\"fehler_adresse\":\"That address cannot be used.\",\"fehler_zaehler\":\"The rate counter is unavailable, so nothing was checked.\",\"fehler_pruefdienst\":\"The reCAPTCHA service could not be reached.\",\"fehler_aufbau\":\"The service is not configured correctly. The fault is on this side.\",\"fehler_eingabe\":\"The request could not be read.\",\"fehler_methode\":\"Wrong request method.\",\"fehler_netz\":\"The service could not be reached.\",\"fehler_antwort\":\"The answer could not be read.\",\"fehler_unbekannt\":\"Something went wrong that has no message of its own.\",\"grund_leer\":\"Nothing was entered.\",\"grund_zu_lang\":\"The input is too long.\",\"grund_unlesbar\":\"It does not parse as a host name.\",\"grund_schema\":\"Only http and https hosts are inspected.\",\"grund_benutzerinfo\":\"Inputs with credentials in them are refused.\",\"grund_kein_punkt\":\"The host name needs at least one dot.\",\"grund_hostform\":\"Enter a host name, not an IP address.\",\"grund_port\":\"Only the ports 80, 443, 8080 and 8443 are inspected.\",\"grund_gesperrter_bereich\":\"That host resolves into a private or reserved network. Those are never contacted.\",\"grund_kein_dns\":\"The host name does not resolve.\",\"befund_soft_404\":\"Soft 404 at {pfad} || The server answered 200 with an HTML page instead of the file or a 404. Crawlers and tools that look for this file get a web page and either misparse it or treat the file as present. A real 404 is the honest answer.\",\"befund_security_fehlt\":\"No security.txt || RFC 9116 defines where security researchers find a contact: \\\/.well-known\\\/security.txt. Without it, a report about a vulnerability goes to whatever address someone guesses, or nowhere. Two lines, Contact and Expires, are enough.\",\"befund_security_nur_alt\":\"security.txt only at the legacy path \\\/security.txt || The standard location is \\\/.well-known\\\/security.txt; the root path is a fallback that tools still try. Serving it at both is the recommendation.\",\"befund_security_alt_fehlt\":\"security.txt not mirrored at \\\/security.txt || Optional: older tools look at the root. A redirect from \\\/security.txt to the well-known path covers them.\",\"befund_security_vorhanden\":\"security.txt present (fields: {felder}; signed: {signiert}) || The file exists at the standard path and parses.\",\"befund_security_contact_fehlt\":\"security.txt without Contact || Contact is the one mandatory field; without it the file serves no purpose.\",\"befund_security_contact_form\":\"Contact is not a URI: {wert} || Contact must be a mailto:, https: or tel: URI. A bare address is not valid under RFC 9116, although many readers cope.\",\"befund_security_expires_fehlt\":\"security.txt without Expires || Expires is mandatory since RFC 9116. Without it, a reader cannot tell whether the contacts are still current.\",\"befund_security_expires_unlesbar\":\"Expires is not a valid date: {wert} || The value must be an ISO 8601 date-time such as 2027-03-01T00:00:00.000Z.\",\"befund_security_abgelaufen\":\"security.txt expired on {datum} || An expired file must be treated as stale. The contacts may still work, but the standard says not to rely on them. Refreshing Expires once a year is the usual routine.\",\"befund_security_expires_lang\":\"Expires more than a year ahead ({datum}) || RFC 9116 recommends an expiry within a year, so the file is reviewed regularly. Not an error, but a sign the file may be forgotten.\",\"befund_security_expires_ok\":\"Valid until {datum} ({tage} days) || The file is current.\",\"befund_security_expires_mehrfach\":\"Several Expires fields || Only one is allowed; readers may reject the file.\",\"befund_security_canonical_fremd\":\"Canonical points elsewhere: {wert} || Canonical must list the URL the file is actually served from. A mismatch suggests the file was copied from another host.\",\"befund_security_canonical_fehlt\":\"No Canonical field || Optional, but together with a signature it proves the file belongs to this host and was not planted elsewhere.\",\"befund_security_unsigniert\":\"security.txt is not signed || Optional: an OpenPGP signature lets a researcher verify the file was not tampered with. Most sites skip it.\",\"befund_security_encryption_fehlt\":\"No Encryption field || Optional: a link to a public key lets researchers send reports encrypted.\",\"befund_security_sprachen_fehlen\":\"No Preferred-Languages field || Optional: tells researchers which languages the contact reads.\",\"befund_security_zeilen_unlesbar\":\"{n} line(s) in security.txt do not parse || Lines must be Field: value or comments starting with #. Readers ignore the rest, but it suggests a formatting slip.\",\"befund_security_content_type\":\"security.txt served as {typ} || The file must be served as text\\\/plain. Some readers refuse other types.\",\"befund_robots_vorhanden\":\"robots.txt present: {gruppen} group(s), {disallow} Disallow line(s), {sitemaps} Sitemap line(s) || The crawler rules file exists and parses at a glance.\",\"befund_robots_wellknown_gesperrt\":\"robots.txt disallows \\\/.well-known\\\/ || Crawlers that respect robots.txt then skip security.txt, gpc.json and the app association files, and tools that check robots first report them as blocked.\",\"befund_robots_fehlt\":\"No robots.txt || Crawlers treat a missing file as permission to crawl everything. Common and harmless; a file is only needed to exclude something or to name the sitemap.\",\"befund_ads_vorhanden\":\"ads.txt present: {eintraege} entries ({direct} DIRECT, {reseller} RESELLER, {domains} systems), OWNERDOMAIN {owner} || The authorised digital sellers file exists. Ad buyers check it before bidding on this domain\\u0027s inventory.\",\"befund_ads_ungueltig\":\"{n} line(s) in ads.txt do not parse || Each entry needs domain, publisher ID and DIRECT or RESELLER. Malformed lines are ignored by buyers, so the seller they were meant to authorise is not authorised.\",\"befund_ads_leer\":\"ads.txt exists but lists no sellers || An empty file tells buyers that nobody may sell this inventory, which is a valid statement for a site without ads.\",\"befund_ads_ownerdomain_fehlt\":\"No OWNERDOMAIN in ads.txt || The variable names the owner of the site and is required since ads.txt 1.1 when the site belongs to a group; it helps buyers tell owned from managed inventory.\",\"befund_ads_content_type\":\"ads.txt served as {typ} || The IAB specification requires text\\\/plain.\",\"befund_app_ads_vorhanden\":\"app-ads.txt present: {eintraege} entries ({direct} DIRECT, {reseller} RESELLER, {domains} systems) || The mobile app counterpart of ads.txt exists.\",\"befund_app_ads_ungueltig\":\"{n} line(s) in app-ads.txt do not parse || Malformed entries are ignored by buyers.\",\"befund_app_ads_leer\":\"app-ads.txt exists but lists no sellers || Valid, but unusual for a domain that publishes the file.\",\"befund_app_ads_content_type\":\"app-ads.txt served as {typ} || The specification requires text\\\/plain.\",\"befund_ads_fehlt\":\"No ads.txt or app-ads.txt || Only relevant for sites that sell advertising programmatically. Without ads.txt, buyers using it treat all inventory as unauthorised.\",\"befund_gpc_unlesbar\":\"gpc.json does not parse || The file must be JSON with a boolean gpc field, for example {\\u0022gpc\\u0022: true, \\u0022lastUpdate\\u0022: \\u00222026-01-01\\u0022}.\",\"befund_gpc_ja\":\"gpc.json declares that Global Privacy Control is honoured (last update {lastUpdate}) || The site tells visitors\\u0027 browsers and regulators that a Sec-GPC signal is treated as an opt-out from sale and sharing.\",\"befund_gpc_nein\":\"gpc.json declares that Global Privacy Control is not honoured (last update {lastUpdate}) || The file exists and says gpc: false. Honest, but rarely what a site wants to publish.\",\"befund_gpc_ohne_datum\":\"gpc.json without lastUpdate || Recommended so readers can tell how current the declaration is.\",\"befund_gpc_content_type\":\"gpc.json served as {typ} || The specification asks for application\\\/json.\",\"befund_gpc_fehlt\":\"No gpc.json || Optional. A site that honours Global Privacy Control can say so here; California\\u0027s regulator points to it as one way to document compliance.\",\"befund_llms_vorhanden\":\"llms.txt present: {links} link(s) in {abschnitte} section(s), {kb} KB || The Markdown file for language models exists. It is a proposal, not a standard; few crawlers read it yet.\",\"befund_llms_ohne_h1\":\"llms.txt without a top-level heading || The proposal requires a single H1 with the site name as the first line.\",\"befund_llms_ohne_zitat\":\"llms.txt without a summary blockquote || The proposal recommends a short blockquote below the heading that summarises the site.\",\"befund_llms_fehlt\":\"No llms.txt || Optional and still a proposal. It does nothing for the AI crawlers that matter today; robots.txt is where their access is controlled.\",\"befund_change_password_ok\":\"change-password redirects to {ziel} || Password managers open this path to lead users to the password change form. The redirect is the intended implementation.\",\"befund_change_password_seite\":\"change-password answers with a page directly || Works if the page is the password form. A redirect to the real form is the more common implementation.\",\"befund_change_password_fehlt\":\"No change-password || Optional, and only relevant for sites with accounts. One redirect line makes password managers\\u0027 change-password buttons work.\",\"befund_change_password_soft\":\"change-password answers 200 with a generic page || Password managers cannot tell this from a real target. The specification asks for a redirect or a real 404, and recommends that \\\/.well-known\\\/resource-that-should-not-exist-whose-status-code-should-not-be-200 returns a 404.\",\"befund_assetlinks_unlesbar\":\"assetlinks.json does not parse || Android App Links and credential sharing depend on this JSON; a syntax error switches them off.\",\"befund_assetlinks_vorhanden\":\"assetlinks.json present: {n} statement(s), package(s) {pakete} || Android app links and shared credentials are declared.\",\"befund_assetlinks_content_type\":\"assetlinks.json served as {typ} || Android requires application\\\/json; other types are rejected.\",\"befund_aasa_unlesbar\":\"apple-app-site-association does not parse || Universal Links and shared web credentials on iOS depend on this JSON.\",\"befund_aasa_vorhanden\":\"apple-app-site-association present (keys: {schluessel}) || The iOS association file exists.\",\"befund_aasa_content_type\":\"apple-app-site-association served as {typ} || Apple\\u0027s CDN fetches it and expects application\\\/json; other types are ignored.\",\"befund_traffic_advice_unlesbar\":\"traffic-advice does not parse || The file must be a JSON array of advice objects.\",\"befund_traffic_advice_vorhanden\":\"traffic-advice present (prefetch fraction {fraction}) || The site tells Chrome\\u0027s prefetch proxy how much speculative traffic it accepts.\",\"befund_humans_vorhanden\":\"humans.txt present || A note about the people behind the site. Purely informational.\",\"befund_sitemap_vorhanden\":\"sitemap.xml present ({art}, {n} loc entries) || The sitemap exists at the default path.\",\"befund_sitemap_kein_xml\":\"sitemap.xml is not a sitemap ({typ}) || The path answers, but not with a urlset or sitemapindex document.\",\"befund_sitemap_fehlt\":\"No sitemap.xml at the default path || Common when the sitemap lives elsewhere and is announced in robots.txt or Search Console.\"};<\/p>\n<p>    var ENDPUNKT = '\/lw-wellknown.php';\n    var SITEKEY = '6LcrPkEtAAAAAPo1QCOf-IIM2fCL0UfdJz4y2iSY';\n    var STUFEN = ['hoch', 'mittel', 'niedrig', 'info', 'gut'];\n    var ZUSTAENDE = ['vorhanden', 'fehlt', 'soft_404', 'weitergeleitet', 'fehler', 'status', 'leer'];<\/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) { if (bytes === null) { return '-'; } if (bytes < 1024) { return bytes + ' B'; } return (Math.round(bytes \/ 102.4) \/ 10) + ' KB'; }\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) }; }\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 z = (a.zaehlung &#038;&#038; typeof a.zaehlung === 'object') ? a.zaehlung : {};\n        return {\n            fehler: null, basis: a.basis ? String(a.basis) : '', host: a.host ? String(a.host) : '',\n            urteil: (a.urteil === 'gut' || a.urteil === 'warnung' || a.urteil === 'kritisch') ? a.urteil : 'kritisch',\n            zaehlung: { vorhanden: zahl(z.vorhanden) || 0, fehlt: zahl(z.fehlt) || 0, soft_404: zahl(z.soft_404) || 0, weitergeleitet: zahl(z.weitergeleitet) || 0, fehler: zahl(z.fehler) || 0 },\n            dateien: liste(a.dateien).map(function (f) { f = f || {}; return { key: String(f.key || ''), pfad: String(f.pfad || ''), zustand: ZUSTAENDE.indexOf(f.zustand) === -1 ? 'fehler' : f.zustand, status: zahl(f.status), contentType: f.content_type ? String(f.content_type) : null, bytes: zahl(f.bytes), spruenge: zahl(f.spruenge) || 0, endurl: f.endurl ? String(f.endurl) : null }; }),\n            befunde: befunde, gruppen: gruppen, 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: 'wellknown' }).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.WK = { bewerten: bewerten, darstellen: null, text: text, kb: kb, ENDPUNKT: ENDPUNKT, STUFEN: STUFEN, ZUSTAENDE: ZUSTAENDE, T: T };\n\n    var btn = document.getElementById('wk-btn');\n    var out = document.getElementById('wk-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    var ZUSTAND_FARBE = { vorhanden: GUT, fehlt: GRAU, soft_404: WARN, weitergeleitet: '', fehler: ROT, status: WARN, leer: WARN };\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\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 6px;' + URTEIL[b.urteil], T['urteil_' + b.urteil]));\n        ziel.appendChild(el('p', ZELLE + ' margin: 0 0 12px;', text('zusammenfassung', { basis: b.basis, vorhanden: b.zaehlung.vorhanden + b.zaehlung.weitergeleitet, gesamt: b.dateien.length, soft: b.zaehlung.soft_404 })));\n\n        ziel.appendChild(el('div', UEBERSCHRIFT, T.h_dateien));\n        var huelle = el('div', 'overflow-x: auto;');\n        var gp = gitter('auto auto auto auto auto');\n        [T.spalte_pfad, T.spalte_zustand, T.spalte_status, T.spalte_typ, T.spalte_groesse].forEach(function (s) { gp.appendChild(el('div', ZELLE + ' font-weight: 700; color: var(--text-primary, #e8e8ee); white-space: nowrap;', s)); });\n        b.dateien.forEach(function (f) {\n            gp.appendChild(el('div', ZELLE_WERT + ' white-space: nowrap;', f.pfad));\n            gp.appendChild(el('div', ZELLE_WERT + ZUSTAND_FARBE[f.zustand] + ' white-space: nowrap;', T['zustand_' + f.zustand] + (f.zustand === 'weitergeleitet' &#038;&#038; f.endurl ? ' \u2192 ' + f.endurl : '')));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, f.status === null ? '-' : String(f.status)));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, f.contentType || '-'));\n            gp.appendChild(el('div', ZELLE_WERT + GRAU, f.zustand === 'vorhanden' ? kb(f.bytes) : '-'));\n        });\n        huelle.appendChild(gp);\n        ziel.appendChild(huelle);\n        var g = gitter('auto auto');\n        if (b.dauer !== null) { paar(g, T.zeile_dauer, b.dauer + ' ms', 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_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.WK.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('wk-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>Fetches the thirteen policy files a domain can publish at fixed paths, from security.txt and robots.txt to ads.txt, gpc.json, llms.txt, change-password, assetlinks and the Apple app association, and checks each against its own rules: present, expired, soft 404, wrong content type, unreadable.<\/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,91094,91115],"class_list":["post-15564","page","type-page","status-publish","hentry","tag-prywatnosc-danych-pl","tag-seo","tag-web-security"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Well-known &amp; Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt - 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\/well-known-policy-files-inspector-security-txt-ads-txt\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Well-known &amp; Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Fetches the thirteen policy files a domain can publish at fixed paths, from security.txt and robots.txt to ads.txt, gpc.json, llms.txt, change-password, assetlinks and the Apple app association, and checks each against its own rules: present, expired, soft 404, wrong content type, unreadable.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/\" \/>\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\\\/en\\\/toolbox\\\/well-known-policy-files-inspector-security-txt-ads-txt\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/well-known-policy-files-inspector-security-txt-ads-txt\\\/\",\"name\":\"Well-known & Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-05T12:29:45+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/well-known-policy-files-inspector-security-txt-ads-txt\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/well-known-policy-files-inspector-security-txt-ads-txt\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/well-known-policy-files-inspector-security-txt-ads-txt\\\/#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\":\"Well-known &#038; Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt\"}]},{\"@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":"Well-known & Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt - 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\/well-known-policy-files-inspector-security-txt-ads-txt\/","og_locale":"en_US","og_type":"article","og_title":"Well-known & Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt - Lukas Wojcik - Blog","og_description":"Fetches the thirteen policy files a domain can publish at fixed paths, from security.txt and robots.txt to ads.txt, gpc.json, llms.txt, change-password, assetlinks and the Apple app association, and checks each against its own rules: present, expired, soft 404, wrong content type, unreadable.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/","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\/en\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/","name":"Well-known & Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-05T12:29:45+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/well-known-policy-files-inspector-security-txt-ads-txt\/#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":"Well-known &#038; Policy Files Inspector: security.txt, ads.txt, gpc.json, llms.txt"}]},{"@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\/15564","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=15564"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/15564\/revisions"}],"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=15564"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=15564"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}