{
  "id": 231103,
  "title": "Why your bot gets 403 from Cloudflare (and how to harden a ccxt client)",
  "url": "https://urgent.news/2026/08/06/por-que-tu-bot-recibe-403-de-cloudflare-y-como-endurecer-un-cliente",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-08-06T18:31:54.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/isazajuancarlos/por-que-tu-bot-recibe-403-de-cloudflare-y-como-endurecer-un-cliente-ccxt-2nme"
  },
  "original_language": "es",
  "account": "If you automate an exchange with ccxt, sooner or later you'll see it in the logs: short bursts of 403 Forbidden hitting fetch_balance, OHLCV, or earn balance, which disappear on their own after a few minutes. It's not that your API key is bad. It's the WAF (Cloudflare) that many exchanges put in front of their REST, challenging something that \"looks like a bot\". And your bot is a bot — but a legitimate one, operating your own account against the official API. The problem isn't with permissions, it's with HTTP client reputation. This is about reducing WAF false positives, not evading any access control.\n\nTwo layers mitigate this:\n\nI took this pattern from my own bot on OKX, after several bursts of 403, and published it as a library: ccxt-resilience (Apache-2.0).\n\n1. Make the WAF challenge less: harden\nA default ccxt client announces itself as it is. Adjusting a browser User-Agent, the Accept-Language header, and a loose timeout makes Cloudflare challenge it less frequently:\n\n```python\nimport ccxt\nfrom ccxt_resilience import harden\nexchange = harden(ccxt.okx({\n\"apiKey\": ...,\n\"secret\": ...,\n\"password\": ...,\n}))\n```\n\nharden touches an already built client, returns the same object (chainable), and never breaks its construction: if something fails when setting attributes, it leaves them as they were.\n\n2. Retry only what's due: with_retry\nThe temptation is to wrap everything in a try/except that retries. This is a trap: retrying a credentials or funds error only wastes time, ends up just as bad, and hides logic bugs behind waits. The key is to retry only transient ones — 403/Cloudflare, 429, timeouts — with exponential backoff and jitter, and re-throw real errors right away:\n\n```python\nfrom ccxt_resilience import with_retry\nbalance = with_retry(exchange.fetch_balance)\nohlcv = with_retry(exchange.fetch_ohlcv, \"BTC/USDT\", timeframe=\"1m\", attempts=4, base=1.0, max_s=8.0)\n```\n\nAn authentication error is re-thrown immediately, without retrying. And if attempts are exhausted, the last exception is re-thrown, so your fail-safe handler keeps governing (e.g., returning the last cached value).\n\nThe i-th attempt wait is min(max_s, base * 2**i) + rand()*base: it grows bounded and jitter avoids multiple clients from retrying in sync.\n\nClassification is explicit\nWhat makes an exception retryable or not isn't hidden: it's a function you can inspect and replace.\n\n```python\nfrom ccxt_resilience import is_transient_error\n# A Cloudflare 403? Yes. An invalid key? No.\nis_transient_error(Exception(\"403 Forbidden Cloudflare\")) # True\nis_transient_error(Exception(\"invalid api key\")) # False\n```\n\nWith ccxt installed, it also classifies by exception type (DDoSProtection, RequestTimeout…); without it, by message. That's why ccxt is a soft dependency: the library works with or without it. And if your case is another API, with_retry accepts your own retry predicate.\n\nInstallation\npip install ccxt-resilience\n\nThe code, tests, and details are in the repo: github.com/isazajuancarlos/ccxt-resilience. It's small, stateless infrastructure; use it part by part.",
  "summary": "Si automatizas un exchange con ccxt , tarde o temprano lo verás en los logs: rachas cortas de 403 Forbidden que pegan a fetch_balance , a los OHLCV o al saldo de earn, y que desaparecen solas a los pocos minutos. No es que tu API key esté mal. Es el WAF (Cloudflare) que muchos exchanges ponen delante de su REST, challengueando a algo que \"parece un bot\". Y tu bot es un bot — pero uno legítimo ,…",
  "key_points": [
    "403 Forbidden errors occur during ccxt automation, challenging bot activity",
    "Two mitigation layers: harden client and retry only transient issues",
    "ccxtresilience library provides harden function and istransienterror function"
  ],
  "editors_take": "Mitigating Cloudflare's false positive 403 errors requires adjusting client settings and selectively retrying transient issues, allowing legitimate bots to maintain uninterrupted access to exchange APIs.",
  "illustration": "https://urgent.news/ill/231103.png",
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}