Skip to content
Proxy · Use case

Find out which bot protection a site uses before you retry

To detect antibot protection reliably, you need more than a 403: you need to know that a shield answered instead of the site, and which one. Crawlers, link preview services, SEO tools and data pipelines all treat those failures as random noise and retry them blindly. is-antibot, the open-source library Microlink uses for this check, names the provider from the response you already have, so each blocked URL gets the right next step.

The problem

A blocked response looks like a success until you know who answered

Blocks come from named providers, and each one blocks differently. Cloudflare serves a “Just a moment” interstitial, DataDome scores request signatures in real time, Akamai Bot Manager blocks datacenter IPs at the edge, PerimeterX leans on client-side fingerprinting, and a reCAPTCHA or hCaptcha widget can sit in front of all of them. Some of these arrive as a 403, some as a 429, and some as a 200 with a challenge page for a body.

Hand-written detection does not keep up. A check for “Just a moment” in the HTML catches one Cloudflare mode and misses the rest; a status code check misses every challenge served on a 200. And treating all failures alike is costly: a retry strategy that works against one system can make the next request look more suspicious to another.

is-antibot reads the status code, headers, cookies, body markers and URL of a response and returns whether a block was detected, the provider behind it and which signal matched. It covers 30+ antibot and CAPTCHA providers, it is dependency-free, and it does not try to solve challenges. The Microlink API runs the same detection as one of its first checks: free requests fail with EPROXYNEEDED, and on Pro the blocked request is routed through the proxy.

How it works

How to detect which antibot protection a site uses

Classify your own responses with is-antibot, and let the API handle the ones that are blocked. The API tells you that a URL is protected; only the library tells you by whom.

1 · Name the provider from a response
import isAntibot from 'is-antibot'

const url = 'https://www.example.com/pricing'
const response = await fetch(url)

const { detected, provider, detection } = isAntibot({
  url: response.url,
  statusCode: response.status,
  headers: response.headers,
  html: await response.text()
})

console.log(detected, provider, detection)
// => true 'cloudflare' 'html'

Install it with npm install is-antibot. detected says whether a shield answered, provider names it and detection reports which signal matched: statusCode, headers, cookies, html or url.

2 · The API’s answer on the free endpoint
curl 'https://api.microlink.io/?url=https%3A%2F%2Fwww.example.com%2Fpricing&meta=false'

Without an API key, a protected target fails with EPROXYNEEDED: “The URL provided uses antibot protection. Upgrade to a Pro plan.” It confirms protection is there, but the response does not name the provider.

3 · Route only the blocked URLs
import createClient from 'microlink.io'

const microlink = createClient({
  apiKey: process.env.MICROLINK_API_KEY
})

import isAntibot from 'is-antibot'

const read = async url => {
  const response = await fetch(url)
  const html = await response.text()
  const { detected } = isAntibot({
    url: response.url,
    statusCode: response.status,
    headers: response.headers,
    html
  })
  return detected ? microlink.html(url) : html
}

Your own fetch serves the open sites. When a shield answers, the same URL goes to the API with your Pro key, where the proxy route is automatic, and resolves to the rendered HTML.

Parameters used
  • proxy Automatic on Pro. Set it only to pin a country or to use your own proxy.
  • retry Server-side retries with exponential backoff for intermittent challenges. Default 2.
  • ttl Caches the unblocked response from 1 minute to 31 days. Pro plans.

The full list of error codes, EPROXYNEEDED and EPROXY included, is in the error codes reference. If a provider keeps blocking after you know its name, the fix is usually on the routing side: see how to fix 403 and 429 errors.

Why it works

Why antibot detection comes before any retry

Detection is the decision point. Knowing who answered tells you whether to route, wait, skip or stop spending requests on a URL.

01 · Open source
The same check the API runs, in your code.
is-antibot is published on npm and GitHub, dependency-free and deterministic, so it can run on every response without becoming the bottleneck. You can audit exactly how each provider is matched.

The antibot feature page lists the providers and explains how the API uses the result.

02 · Provider, not guess
Named across 30+ antibot and CAPTCHA systems.
Cloudflare, DataDome, Akamai Bot Manager, PerimeterX, Kasada, Imperva, AWS WAF and Vercel Attack Mode on the antibot side; reCAPTCHA, hCaptcha, FunCaptcha, GeeTest and Cloudflare Turnstile among the CAPTCHAs.

For the most common case, scraping Cloudflare-protected sites walks through what happens after detection.

03 · Detection, not solving
It tells you who blocked you, not how to get past.
The library never touches the challenge. Getting a legitimate request through is the proxy’s job, which on Pro plans escalates blocked requests through proxy tiers up to residential IPs.

When not to: if every URL you fetch already goes through the API on a Pro plan, you do not need client-side detection at all, because the proxy route is automatic. Compare plans on the pricing page.

FAQ

How do I detect if a site uses Cloudflare bot protection?

Fetch the page and pass the response’s status, headers, URL and HTML to is-antibot. If detected is true and provider is cloudflare, a Cloudflare challenge or block answered instead of the site.
No. The API runs antibot detection internally and acts on it: the free endpoint fails with EPROXYNEEDED and Pro routes the request through the proxy. The provider name is only exposed by the is-antibot library.

Which bot protection providers can is-antibot detect?

More than 30, covering antibot systems such as Cloudflare, DataDome, Akamai Bot Manager, PerimeterX, Kasada, Imperva and AWS WAF, and CAPTCHA providers such as reCAPTCHA, hCaptcha, FunCaptcha, GeeTest and Cloudflare Turnstile.

Can is-antibot get my scraper past a bot challenge?

No. It does not try to solve challenges; it only detects them and names the provider. To fetch the blocked page, send it through the API on a Pro plan, where automatic proxy resolution handles the route.

What does EPROXYNEEDED tell me about a site’s bot protection?

That the site uses antibot protection and the request cannot succeed on the free plan. It is the signal to upgrade to Pro, where the same request is routed through the proxy automatically, not a parameter to add.
Related use cases

Solve the next problem with the same API

Scrape Cloudflare-protected websites

Get the real page instead of “Just a moment”: on Pro plans, blocked requests escalate through proxy tiers up to residential IPs.

Fix 403 and 429 scraping errors

Tell an antibot 403, a throttling 429 and your own quota apart, then route, cache or wait accordingly.

Link previews for bot-protected sites

Unfurl links to sites behind Cloudflare or DataDome: on a Pro key the built-in proxy resolves automatically.

Ready to see who is blocking you?

Name the provider with is-antibot, then let a Pro key route the blocked URLs through the proxy.