A fixture-first Python lab for deciding when to keep a proxy session, when a transport-only rotation is safe, when to honor Retry-After, and when an explicitly detected CAPTCHA may enter one bounded CapSolver recovery step.
English · 简体中文 · 日本語 · Español · Português · 한국어
Generic rotation loops often treat 403, 407, 429, timeouts, and CAPTCHA pages as interchangeable reasons to switch IPs. They are different failure classes:
429is an origin rate-limit signal. Respect its cooldown instead of assuming another IP grants permission to continue.407is a proxy configuration or authentication problem.- A proxy connect timeout can justify one rotation for a stateless request, but rotating a stateful browser or form session can invalidate cookies and server-side state.
401or403alone does not prove that a supported CAPTCHA exists.- A CAPTCHA result belongs to the proxy, cookie jar, User-Agent, origin, purpose, and authorization context used to create it.
This repository turns those distinctions into tested decisions. CapSolver appears only in the explicitly classified, authorized challenge branch.
| Observation | Default action | Rotate? | CapSolver? |
|---|---|---|---|
| Expected record in a 2xx response | Accept | No | No |
429 Too Many Requests |
Honor Retry-After and cool down |
No | No |
407 Proxy Authentication Required |
Stop and fix configuration | No | No |
| Proxy transport failure, stateless request | Rotate once within budget | Once | No |
| Proxy transport failure, stateful request | Stop to preserve session context | No | No |
| Transient 5xx response | Retry once with the same context | No | No |
401/403 without explicit challenge classification |
Stop and review access | No | No |
| Explicit supported challenge with authorization | Request one bounded recovery | No | Once |
The 429 behavior follows RFC 6585, which allows an origin to communicate a wait interval with Retry-After. The session model follows the Requests Session documentation: sessions persist cookies and other parameters across requests.
response or transport error
│
▼
explicit classifier
│
├── 429 ───────────────► cool down
├── 407 / 401 / plain 403 ► stop and inspect
├── proxy transport ───► rotate only if stateless + budget remains
├── 5xx ───────────────► retry same session once
└── typed challenge ───► authorization + context fingerprint
│
▼
one CapSolver recovery request
│
matching context? ─┴─ yes: return once and verify data
no: stop
Requires Python 3.11 or newer. Tests and examples use fixtures and make no external requests.
python -m venv .venv
source .venv/bin/activate
python -m pip install -e .
python -m unittest discover -s tests -v
python scripts/smoke_test.py
python examples/run_lab.pyExpected smoke output:
SMOKE PASSED: 429 cooled down; matching challenge recovered once; replay stopped
SessionContext records non-secret identifiers for the active request context:
from proxy_captcha_lab import SessionContext
context = SessionContext(
origin="https://qa.example.test",
proxy_id="sticky-session-a",
cookie_jar_hash="cookie-fixture-v1",
user_agent="session-lab/0.1",
authorization_ref="QA-42",
)Store a digest or opaque cookie-jar identifier, not raw cookies. SessionContext.fingerprint changes if the proxy, cookie digest, User-Agent, origin, purpose, or authorization reference changes.
Observation keeps failure classification explicit:
from proxy_captcha_lab import Observation
rate_limited = Observation(status_code=429, retry_after_seconds=30)
plain_forbidden = Observation(status_code=403)
typed_challenge = Observation(status_code=403, challenge_type="supported-demo")The lab never infers a CAPTCHA from an HTTP status alone. Production detection must be based on a supported challenge type observed in target-owner-approved code.
RecoveryCoordinator checks the decision budget and compares the result's context fingerprint with the active session before returning it:
from proxy_captcha_lab import FixtureGateway, RecoveryCoordinator
coordinator = RecoveryCoordinator(FixtureGateway())
decision = coordinator.handle(typed_challenge, context, stateful=True)
print(decision.action)The fixture gateway proves the orchestration without sending a token or API key. To build a real authorized adapter, construct task fields from the current CapSolver createTask contract and poll only according to the getTaskResult contract. Page-specific application remains the target owner's responsibility.
- Proxy acquisition, free-proxy lists, or provider recommendations.
- Automatic rotation after rate limits or access denials.
- Fingerprint spoofing, challenge concealment, or access-control evasion.
- Raw cookie, token, credential, or browser-profile storage.
- Site-specific token injection or unsupported challenge types.
- Unbounded retries, concurrency, or collection.
The suite verifies:
Retry-Afteris honored without rotation.- Plain 403 responses do not trigger CAPTCHA handling.
- Proxy authentication failures stop.
- Stateful transport failures preserve context and stop.
- Stateless transport failures rotate at most once.
- 5xx responses retry once on the same context.
- Missing authorization blocks recovery.
- Matching recovery context returns once.
- Mismatched context is rejected.
- Changing the proxy changes the session fingerprint.
Use this repository only for public data, systems you own, or targets covered by explicit written authorization. Follow applicable terms, access policies, privacy rules, request limits, and retention requirements. A CAPTCHA-solving capability does not grant permission to access private, restricted, sensitive, or unauthorized data.
Keep request rates bounded, retain only the evidence needed for debugging, redact credentials and cookies, and stop when the business record is still absent after the approved recovery attempt.
src/proxy_captcha_lab/ Classifier, policy, coordinator, and fixture gateway
tests/ Offline unit tests
examples/ Three-observation decision walkthrough
scripts/ Deterministic smoke test
research/ Topic deduplication and source verification
docs/zh-CN/ Chinese project summary
Read CONTRIBUTING.md before changing decision semantics. Report sensitive problems according to SECURITY.md; never put API keys, proxy credentials, cookies, solution payloads, or private target URLs in an issue.
No. It tests when rotation would be permitted by policy; it does not acquire proxies or make live proxy requests.
No. A 403 can represent authorization, policy, configuration, or other access failures. The lab requires an explicit supported challenge classification.
A 429 communicates that the origin is rate limiting requests. The safe default is to honor the cooldown and reduce request pressure, not to treat another IP as permission to continue.
Yes, for an authorized workflow. Keep the same context binding and attempt budget, use only current official task contracts, and verify the intended business record after the result is applied.
No. This is an independent, educational lab maintained as a CapSolver integration example; it is not a proxy product or replacement SDK.
This fixture-first lab keeps proxy transport decisions, origin rate limits, access denials, and typed challenges separate. It preserves stateful session affinity, binds every approved recovery to an auditable context fingerprint, and permits at most one authorized CapSolver recovery.
Developer sharing CapSolver integration examples.
