AI OFF

Wire up the button.

Everything connects to a switch through one public status URL. First create a switch to get its ID.

Embed on a website

Add this before the closing </body> tag of any page:

html
<script src="https://ai-off.netlify.app/embed.js" data-switch="YOUR_SWITCH_ID" async></script>

While AI is off, the script:

  • hides every element marked as AI content;
  • blocks fetch, XHR, WebSocket and EventSource calls from the page to major AI providers (OpenAI, Anthropic, Google Gemini, Mistral, Cohere, Groq, OpenRouter, Hugging Face and others);
  • adds a noai, noimageai robots tag;
  • sets window.AI_OFF = true and data-ai-off="true" on <html>.

Visitors can press the floating button to switch AI off for themselves. When you switch it off from your control panel, it's off for everyone and the button shows LOCKED. The script re-checks every 10 seconds.

AttributeMeaning
data-switchYour switch ID. Optional — without it, only the visitor toggle works.
data-hideExtra CSS selectors to hide, comma separated. e.g. "#chat-widget, .ai-summary"
data-blockExtra hostnames to block, comma separated. e.g. "llm.mycompany.com"
data-button"false" hides the floating button.
data-positionbottom-right (default), bottom-left, top-right, top-left

Mark AI content

Anything with one of these attributes or classes disappears while AI is off:

html
<div data-ai>AI chat widget</div>
<p data-ai-generated>This summary was written by AI.</p>
<img class="ai-generated" src="/generated.png" alt="…">

Style your own fallbacks with the root attribute:

css
html[data-ai-off="true"] .search-box { /* show classic search */ }

JavaScript API

js
window.AIOff.isOff()        // true | false
window.AIOff.turnOff()      // visitor-level off
window.AIOff.turnOn()
window.AIOff.onChange(({ off, global, local }) => { … })

document.addEventListener('aioff:change', (e) => {
  if (e.detail.off) myChatbot.destroy()
})

Agents & bots

Have your agent read the switch before each action and stop when it says off. Ready-made Node and Python guards are on every switch's control panel.

pseudo-code
loop:
  status = GET https://ai-off.netlify.app/api/switch/YOUR_SWITCH_ID
  if status.ai == "off": stop
  do next step

Treat an unreachable status URL as a reason to pause, not to carry on — that way the switch fails safe.

REST API

EndpointWhat it does
GET /api/switch/:idPublic. Returns { id, name, ai: "on"|"off", aiEnabled, flipCount, updatedAt }. Also sets an X-AI-Status header. Add ?events=1 for the last 20 flips.
POST /api/switch/:idOwner only. Header Authorization: Bearer <admin key>. Body { "ai": "off" | "on" | "toggle", "source"?: "pager" }.
POST /api/switchesCreates a switch. Body { "name" }. Returns the switch and its admin key (shown once).
terminal
curl -X POST https://ai-off.netlify.app/api/switch/YOUR_SWITCH_ID \
  -H "Authorization: Bearer $AIOFF_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ai":"off","source":"on-call"}'