Anti-Bot Systems

When the Solver's IP Matters (and When It Does Not)

Here is a failure that wastes whole afternoons. Your solver returns status: 1 with a long, healthy-looking token. You inject it into exactly the right field. The site rejects it. Resubmit, and the next perfect token is rejected too — while the solver dashboard reports near-100% success and, by its own definition, tells the truth.

Key takeaway: a solved challenge and an accepted challenge are two different events, and the gap between them is usually network context. Some challenge types record the address the solve came from into the artifact you are about to present; when that address is a datacentre range and your session is somewhere else, the artifact is valid and useless at once. Others have no network context at all, and proxying their solves buys nothing but latency. Knowing which family you are in is the whole decision.

Measure two rates, not one

Before touching a proxy parameter, split the metric your solver gives you.

  • Solve rate — how often the API returns an artifact instead of an error. This is what a provider can publish.
  • Acceptance rate — how often the target honours what you present: the form submits, siteverify comes back success: true, the protected page returns 200 instead of another interstitial.

Only the second is your success rate, and no provider can see it — acceptance happens on a request between you and the target that the provider never observes. It also localises the bug: solve rate down is a solver or parameter problem; solve rate high with acceptance low means the artifact was rejected on its merits.

What "context" means, challenge type by challenge type

Being scored by IP and ASN reputation is less a property of the site than of the challenge it serves. How anti-bot detection works covers why that reputation exists; here the question is narrower: does the issuer of this artifact fold the requesting IP into it?

Challenge Is the solve's IP part of the artifact? Proxy?
Image / character CAPTCHA No — it is pixel classification No
Grid image, BLS-style numeric grid No No
reCAPTCHA v2 / v2 Invisible / v2 Enterprise Partly — issued to an observed client Usually
reCAPTCHA v3 / v3 Enterprise Yes — the IP feeds the score baked into the token Yes
Cloudflare Turnstile Partly — issued to an observed client Usually
Cloudflare Challenge Yes — clearance is issued to a session, not to a browser in the abstract Yes
Geetest v3 Partly — depends on the site's verification call Test it

Text answers have no network context at all

An image CAPTCHA is a classification job. You send bytes, a model reads characters, you get a string. Nothing in that exchange touches a network the target can observe — the solve could happen on the moon and the answer would be identical. Grid selections and BLS-style numeric grids behave the same way. CaptchaAI publishes sub-0.5-second times on image work across 27,500+ variants and under a second on grid and BLS types; a proxy hop there is overhead paid against a signal that does not exist.

Scored tokens carry the network in the score

reCAPTCHA v3 is the clearest case, because the scoring is the product. The token is not a pass receipt — it carries a risk assessment computed at issue time from the environment that asked for it, including the requesting address. Earn it from a hosting ASN and the low score travels inside the token; the site's backend reads that number, compares it against a threshold you do not control, and declines. The token is genuine. It is carrying bad news about where it was born.

v2 and Turnstile sit a step softer. Their artifact is nearer a pass receipt, but the issuer still observed a client when it granted the pass, and both verification endpoints accept an optional remoteip from the site's backend. Whether the site sends it is the site's choice — which is why identical automation gets a token accepted on one property and rejected on another running the same widget. You cannot read that config from outside; you can only test it.

Clearance is bound to a session, not to a solve

Cloudflare Challenge punishes carelessness fastest. It guards the page, not a form. Passing it produces a cf_clearance cookie plus the user agent that earned it, and that pairing is load-bearing — CaptchaAI publishes >99% under 15 seconds here and returns both values for a reason. Treat the exit address as part of the pairing too: clearance earned on one network and replayed from another is a session that moved house mid-conversation.

The economics invert here. Token types need one solve per submission and discard the artifact immediately; clearance needs one solve per session, then gets reused across every subsequent request — so you pay the proxy hop once and amortise it over hundreds of page fetches.

Passing a proxy per task

proxy and proxytype attach to the individual task, not to your account — so one pipeline can proxy the types that need it and skip the rest.

curl -s -X POST "https://ocr.captchaai.com/in.php" \
  -d "key=YOUR_API_KEY" \
  -d "method=userrecaptcha" \
  -d "version=v3" \
  -d "action=verify_report" \
  -d "googlekey=6Lc_SITE_KEY_FROM_THE_PAGE" \
  -d "pageurl=https://example.com/reports" \
  -d "proxy=user:pass@203.0.113.10:8080" \
  -d "proxytype=HTTP" \
  -d "json=1"
# {"status":1,"request":"2122988149"}
# Same account, same key, no proxy — an image task has nothing to bind.
curl -s -X POST "https://ocr.captchaai.com/in.php" \
  -d "key=YOUR_API_KEY" \
  -d "method=base64" \
  -d "body=iVBORw0KGgoAAAANSUhEUg..." \
  -d "json=1"

Polling is unchanged either way — GET /res.php?key=YOUR_API_KEY&action=get&id=<taskId>&json=1 roughly every five seconds until CAPCHA_NOT_READY stops coming back.

proxy takes login:password@host:port. proxytype names the scheme — HTTP, HTTPS, SOCKS4, SOCKS5 in this protocol's vocabulary; confirm the exact set against the parameter reference for your method. Three constraints bite in production:

Credential auth only. Providers that authorise by IP allow-list are unusable here — the connection arrives from the solver's infrastructure, not your servers, so there is no address to allow-list.

Sticky sessions. A rotating endpoint that hands out a new exit per connection defeats the purpose exactly: the solve happens somewhere neither you nor the target expects. Ask for a session outlasting that challenge type's published envelope, and hold the same exit for the submission that follows.

Your egress, not "a residential proxy" as a generic upgrade. The goal is coherence between where the artifact was earned and where it is presented; a second unrelated address is still a mismatch, however clean its reputation.

What the hop costs

More than one round trip. A token solve is a whole widget flow — script loads, challenge fetches, verification calls — and every leg now traverses your proxy, so a slow exit stretches the entire solve.

The expense then surfaces somewhere unexpected. CaptchaAI charges for concurrent threads rather than per solve — no per-CAPTCHA fee, no daily cap, no surcharge by type — and a thread is a slot held for as long as a task is in flight, so throughput is roughly threads divided by average solve time. Lift your average v2 solve from 25 to 35 seconds and 50 threads fall from about 2 solves per second to about 1.4: a 29% cut in ceiling with no change to the invoice. Published tiers step BASIC $15/month for 5 threads, ADVANCE $90/month for 50, ENTERPRISE $300/month for 200 — so the correction is a tier, not a line item. Budget the proxy decision in threads.

It also widens your failure surface. A dead exit, an expired credential or a saturated pool rarely announces itself as a proxy problem — it surfaces as a task that never completes or dies with ERROR_UNSOLVABLE, and you go hunting in the wrong system. Tag every task with the exit it used and alert when failures cluster on one.

Decide it with a test, not a rule

Since the deciding factor is server-side configuration you cannot inspect, the honest method is an experiment. Take one target and one challenge type, run two arms of a hundred tasks — one proxyless, one through your session's egress — and record both rates for each. Four outcomes, four conclusions:

  • Both arms accept well. The target does not check the solve's origin. Stay proxyless and keep the latency.
  • Proxied accepts, proxyless does not. Classic context binding. Proxy this type and re-size threads for the slower path.
  • Neither accepts, both solve. Not an IP problem. Look at the injection field, token lifetime, the action on a v3 task, or a pageurl that does not match the page.
  • Proxyless accepts and proxied does not. Your proxy's reputation is worse than the solver's, or the exit is failing — check the pool before blaming the mechanism.

Re-run it when a target's challenge rate shifts. Thresholds get retuned, and last quarter's answer expires quietly.

When it changes nothing

The cases where a proxy is a pure loss:

  • Text-answer challenges. No network context exists to match.
  • Your own staging environment. Google and Cloudflare both publish test site keys that always validate. A QA suite solving real challenges against an app you control is a staging-config problem.
  • Targets that never send remoteip. Plenty of integrations verify a token without passing the client address, and proxying cannot interact with a check that is not happening.
  • When your proxy is another datacentre. Moving between hosting ASNs swaps a bad prior for a bad prior and adds a hop.
  • When the real problem is rate. If you are challenged because you pull two hundred URLs a minute from one host, a cleaner IP delays the diagnosis rather than fixing it. Slow down first, then measure again.

That last point generalises. Proxying is for the challenges left over after you have honoured robots.txt, stayed inside published rate limits and read the target's terms — a monitoring fleet checking endpoints you are permitted to check, a QA suite against your own application, lawful collection of public data. It is a coherence tool, not a disguise, and worth nothing against a target you should not be automating in the first place.

FAQ

Why is my perfectly solved token rejected?

Because solving and acceptance are separate events. If the artifact carries a score or a session binding — reCAPTCHA v3, Cloudflare clearance — a solve from a datacentre range yields a genuine artifact with bad context attached.

Do I need a proxy on every task?

No, and defaulting to yes is expensive. Text-answer types have no network context, so proxying them adds latency to a sub-second job for no gain. Reserve proxies for score-bearing tokens and clearance flows, and decide per type rather than per account.

Does a residential proxy always beat a datacentre one?

Not automatically. You want the address your session will submit from, whatever kind it is. A residential exit shared by hundreds of unrelated sessions an hour trades a reputational signal for a volumetric one.

How much slower are proxied solves?

Enough to plan for, and it varies with your pool rather than the solver. Measure your own before-and-after average and convert it into threads — a slower path needs more slots to hold the same ceiling.

Start with the measurement

Add acceptance rate to your metrics this week, broken down by target host and challenge type. It is a small change that turns this question from opinion into arithmetic — most of your volume typically needs no proxy at all, and one or two routes need it badly.

Then proxy only those routes with the per-task proxy and proxytype parameters, and read the cost in threads rather than as a per-solve surcharge to forecast. The parameter reference, documented error codes and examples in cURL, Python, Node.js, PHP, Go, Java, .NET, Ruby, Rust and Postman are at getcaptchaai.com.

Comments are disabled for this article.