{
  "id": "WEB-098",
  "slug": "web-098",
  "title": "The QR landing page must be publicly reachable",
  "statement": "The page a QR code opens must be fetchable by anyone — no login, geo-gate, app-install wall or captive portal in front of it.",
  "rationale": "A QR code is scanned in a shop, on a table, at an event — and if the page behind it demands an app or a login, the consumer never opts in and the reviewer never sees the surface either. The captive-portal case is the one that catches careful operators: a code that works perfectly on the store Wi-Fi opens nothing at all for someone on a mobile network, and nobody tests it that way.",
  "layer": "WEBSITE",
  "layerSlug": "website",
  "object": "QR destination fetch",
  "severity": "BLOCKING",
  "detectability": [
    "CRAWL"
  ],
  "failureClass": "TERMINAL_WEBSITE",
  "authorities": [
    "Twilio",
    "Bird"
  ],
  "codes": [
    {
      "provider": "Twilio",
      "code": "30909",
      "remediable": true,
      "generation": "gen2"
    },
    {
      "provider": "Bandwidth/DCA",
      "code": "804",
      "remediable": true
    }
  ],
  "applicability": {
    "consentMethods": [
      "qr"
    ]
  },
  "applicabilityText": "Applies when consent was collected by QR code.",
  "universal": false,
  "remediation": "Host the QR destination on a public https page on the brand domain, with no login, no app interstitial and no dependence on the venue network. Done when scanning the code on a phone with mobile data and no app installed shows the opt-in.",
  "pitfalls": [
    "Test the printed code, not the URL. A code printed from a draft, or one pointing at a short link whose account has lapsed, opens something entirely different from what was designed."
  ],
  "phase": "approval",
  "automated": true,
  "url": "https://ekas.io/rules/10dlc/website/web-098/",
  "markdown": "https://ekas.io/rules/10dlc/website/web-098.md",
  "registry": "https://ekas.io/rules/10dlc/",
  "updated": "2026-07-25",
  "licence": "CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/"
}
