Skip to content
Pro feature

Antibot detection: know who blocked your request — and why

The API detects antibot and CAPTCHA challenges from 30+ providers in every HTTP response — reading headers, cookies, HTML, URL, and status code — then routes the request through the resolution path that specific provider requires. No configuration, no retry loops to write.

+700M requests every month

Every scraper is fighting defenses built to stop it

When your infrastructure takes a URL as input, you are constantly interacting with systems designed to keep automation out. A request can experience — followed by a challenge page. A CAPTCHA. A JavaScript puzzle.

Modern antibot systems operate at multiple layers, often before the request even reaches the application code, fingerprinting every hop along the way:

IP reputationHTTP consistencyTLS fingerprints (JA3)behavioral heuristicsJS fingerprinting

Detection does something fundamental: it tells you when a non-success resolution happens and who triggered it, so the next decision — retry, reroute, escalate — is made with real information instead of a blind retry loop.

Illustrative distribution of antibot providers detected across blocked requestsblockedprovidersrecaptchacloudflarecloudflare-turnstileaws-wafakamaihcaptcha
Illustrative provider distribution across blocked requests.
Every response, classified
detection · every request
Allowed
heuristics say human — passed through
Blocked
403 or 429 — refused immediately
Challenged
CAPTCHA or JavaScript interstitial to resolve
Five signals → one verdict

How detection works

Every response is inspected across five signals — headers, cookies, HTML, URL, and status code. Each provider leaves a distinct combination of fingerprints; checks run in priority order and the first match wins. The result is deterministic and fast — designed to run on every request without becoming the bottleneck.

01 · status code
Unusual status patterns
Certain platforms use unusual status codes when blocking automation — LinkedIn can return 999 and Reddit can return 403 on challenge flows. The status code alone is often enough to classify the block.
LinkedIn · 999Reddit · 403
02 · headers
Mitigation headers
Blocking responses usually expose hints in response headers — Cloudflare commonly surfaces cf-mitigated: challenge, while other providers rely on provider-specific header combinations.
cf-mitigated: challengeserver: cloudflare
03 · cookies
Challenge tokens in cookies
Many antibot systems drop mitigation cookies or challenge tokens before serving a block page. Matching those cookie names and values identifies the provider even when headers stay quiet.
mitigation cookieschallenge tokens
04 · html
Known challenge signatures
Challenge pages include recognizable artifacts — CAPTCHA widgets, interstitial templates, challenge tokens, or provider-specific script references embedded in the response body.
CAPTCHA widgetsinterstitial templatesverification scripts
05 · url
Provider-specific redirect fingerprints
Many CAPTCHA vendors resolve challenges on dedicated verification URLs. When a request lands on one of those paths instead of the target page, the provider is identified from the response URL itself.
challenge redirectsverification paths
Coverage

30+ providers detected out of the box

Detection covers antibot systems, CAPTCHA vendors, and platform-specific protection flows. Use this table as a coverage map when building retry logic, escalation rules, or provider-specific analytics in your scraping pipeline.

ProviderCategorySignalsDetection methods
AkamaiAntibot3
HeadersCookiesHTML
AliExpress CAPTCHACAPTCHA2
HTMLURL
AmazonPlatform-specific2
HeadersHTML
AnubisAntibot1
HTML
AWS WAFAntibot3
HeadersCookiesHTML
Captcha.euCAPTCHA2
HTMLURL
CheqAntibot2
HTMLURL
CloudflareAntibot2
HeadersCookies
Cloudflare TurnstileCAPTCHA2
HTMLURL
DataDomeAntibot2
HeadersCookies
DoubanPlatform-specific1
Status Code
DribbblePlatform-specific1
Status Code
Friendly CaptchaCAPTCHA2
HTMLURL
FullStory ChallengeAntibot2
CookiesHTML
FunCaptcha (Arkose Labs)CAPTCHA2
HTMLURL
GeeTestCAPTCHA2
HTMLURL
GooglePlatform-specific1
URL
hCaptchaCAPTCHA2
HTMLURL
HouzzPlatform-specific1
Status Code
Imperva / IncapsulaAntibot3
HeadersCookiesHTML
InstagramPlatform-specific1
HTML
KasadaAntibot2
HeadersHTML
LinkedInPlatform-specific1
Status Code
MeetricsAntibot2
HTMLURL
OculeAntibot2
HTMLURL
PerimeterXAntibot3
HeadersCookiesHTML
QCloud CaptchaCAPTCHA2
HTMLURL
reCAPTCHACAPTCHA2
HTMLURL
ReblazeAntibot2
CookiesHTML
RedditPlatform-specific2
HTMLStatus Code
Shape SecurityAntibot2
HeadersHTML
SucuriAntibot1
HTML
ThreatMetrixAntibot2
HTMLURL
VercelAntibot1
Headers
WeiboPlatform-specific1
HTML
YouTubePlatform-specific1
HTML

Missing a provider or a signal?

and coverage keeps evolving.

Open source

Audit the detection layer yourself

The detection logic that powers Pro is open source as

— static HTTP response analysis with a minimal footprint, no headless browser required. Pass it any response and it tells you who blocked it. Works with fetch, got, axios, or undici.

index.js
import isAntibot from 'is-antibot'

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

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

if (detected) {
  console.log(`Blocked by ${provider} (via ${detection})`)
  // => "Blocked by CloudFlare (via headers)"
}
Detection → resolution

Knowing who blocked you is half the job

On Pro plans, detection is wired straight into resolution: once the provider is identified, the request is routed through the resolution path that protection layer requires — rotating residential IPs, full browser rendering, retries — well-tested across the Top 500 most popular sites worldwide.

A response served through the proxy layer carries x-fetch-mode prefixed with proxy-; when a target requires it and the plan does not include it, the API returns EPROXYNEEDED — so a block is never silent. Available on metadata, HTML, and markdown requests.

Detect the block, resolve it automatically.

Every Pro plan bundles antibot detection with automatic proxy resolution — no proxy pool to manage, no CAPTCHA solver to integrate, no retry loops to write.

Every HTTP response is inspected across five signals — headers, cookies, HTML, URL, and status code. Each provider leaves a distinct combination of fingerprints, like cf-mitigated: challenge for Cloudflare or status code 999 for LinkedIn.
Checks run in priority order and the first match identifies the provider. The analysis is static and deterministic, designed to run on every request without becoming a bottleneck.

Which providers can be detected?

More than 30 providers across three categories: antibot systems (Cloudflare, Akamai, DataDome, PerimeterX, Kasada, Imperva, AWS WAF, Vercel, and more), CAPTCHA vendors (reCAPTCHA, hCaptcha, Cloudflare Turnstile, FunCaptcha, GeeTest, Friendly Captcha), and platform-specific protection flows (LinkedIn, Reddit, Instagram, YouTube).
Coverage keeps evolving — missing providers can be .

Is the detection logic open source?

Yes. The detection layer is published as on GitHub and npm. It performs static HTTP response analysis — no headless browser required — and works with any HTTP client, including fetch, got, axios, and undici.
It does detection only: it tells you which provider blocked a request, not how to solve the challenge. The resolution paths live inside the Microlink API.

What happens after a block is detected?

On Pro plans, the request is automatically routed through the resolution path that provider requires — rotating residential IPs, full browser rendering, retries. A response served through the proxy layer carries x-fetch-mode prefixed with proxy-.
Without a Pro plan, the API returns EPROXYNEEDED, so a block is never silent — see how the proxy works.

Does detection slow down my requests?

No. Detection is static response analysis — headers, cookies, HTML, URL, and status code are checked against known fingerprints without launching a browser or making extra network calls. The result is deterministic and fast, which is why it runs on every request that goes through the API.