So yesterday, I, like a lot of the internet, found many of my websites down. The issue was not anything to do with me or my servers, but with CloudFlare—a tool I use for DNS and to help with performance and against attacks.

My site was fine, but CloudFlare still wouldn’t let anyone load it.
The most frustrating thing about this situation was that in theory all I had to do was change one flag in my DNS settings—the flag that told CloudFlare to proxy my domain—and everything would work perfectly! The only problem was that CloudFlare itself was also down1, which meant I couldn’t log in to make the simple change.
I could do it from the API if I had an API key, but unfortunately I didn’t, and creating an API key also happens in the dashboard.
In case you ever want to be able to recover from this situation, should it happen in the future, here’s what you can do.
First, right now whilie CloudFlare is up, login to the CloudFlare dashboard and get yourself an API token. You can use the “Edit zone DNS” one.

Under “Zone Resources” chose “All zones from an account” and leave everything else as you found it.

Now we can confirm that we can use the key to do what we want. Set an environment variable:
export CLOUDFLARE_API_TOKEN=<your token>
Next confirm it can list zone IDs:
curl -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
| jq -r '.result[] | "\(.id) \(.name)"'
This will spit out a list of zone id and domain pairs in your account:
a11cb1d0f1a2bf16e8cc0a97c5e3924d coryzue.com
c24e97fe8ec0cbfe5b2b5e03b9b25ec4 lifeweeks.app
3346d3ea04b3ef40c5c62f98e9b884df placecardme.com
ef0a5a0235f2edd0db59c6edef0d1be6 saaspegasus.com
ded991d4b4d9a05e1e4971f8fdb122c3 scriv.ai
Then get a list of dns records for a zone for the site you care about.
export ZONE_ID=<zone for your site>
curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json"
This will return a bunch of JSON you can sift through to find the ID of the record you want to update (it should have "proxied": true).
Then confirm you can patch the relevant record:
export DNS_RECORD_ID=<record id>
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"proxied":false}'
You can check in the CloudFlare dashboard that the record did in fact update, or wait for DNS to propagate and then confirm it’s now routing directly to your server.
Once you’ve confirmed it’s working, you can call the same API to re-enable it:
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"proxied":true}'
Now you’re set up for next time there’s a massive CloudFlare outage!
Thanks to this HN comment for the walkthrough of the API calls to make.
Caveats:
- This assumes your site has its own SSL cert and you aren’t relying on CloudFlare SSL.
- This will, obviously, disable the protection that comes with CloudFlare proxying.
Notes:
-
Or at least down enough that it wasn’t possible to login. ↩