Skip to content

Reliability & retries

bytetourist is built to keep requests flowing even as individual nodes fail, get blocked, or are recycled.

bytetourist tracks the health of every node. When a node fails several requests in a row (currently 5) with no response, a timeout, a dropped stream or a cut-off body (a target’s own 5xx doesn’t count), its breaker trips open and routing prefers other eligible nodes (if every candidate is tripped, the best one is still used). After a cooldown (currently 30 s) it goes half-open and lets one probe request through; if it succeeds the breaker closes and the node resumes normal traffic.

closed ──fail threshold──▶ open ──cooldown──▶ half-open ──success──▶ closed
└────────── failure ─────────────▶ open

This is automatic and per-node; you don’t configure or observe it per request.

The strict flag controls what happens when no node satisfies your targeting constraints (region, country, IP type, protocol):

  • strict=false (default): bytetourist drops the constraints and picks from the whole fleet, so your request still goes out, from wherever that node is.
  • strict=true: bytetourist returns 502 (no X-Proxy-Error slug) rather than relaxing your constraints. Use this when an exact region is non-negotiable.

Unhealthy nodes are handled by the breaker above either way; strict doesn’t change that.

# fail rather than leave from the wrong place
-U "YOUR_API_KEY-cc-de-strict-true:"

Each outbound call is bounded by a per-request timeout (a system-wide setting, currently 30 seconds) covering the whole response. If no response has started by then, you get 598 with X-Proxy-Error: upstream_timeout; a response still streaming when it runs out is cut off. Keep your client timeout a little higher than the proxy’s so you see the proxy’s response rather than your own client abort.

bytetourist does not silently retry your request body: the edge node is a pure L7 proxy with no hidden retry or caching, so behaviour is predictable. For idempotent reads, retry on your side; a retried request is matched afresh and may land on a different node (with freshest_ip / ip_rotation it will, when more than one is eligible).

bytetourist’s own failures carry an X-Proxy-Error header with the slug shown in brackets (branch on the slug, not the number), except 407, 403 and 502, which have none. Any other status is the target’s own response, passed through; a site’s own 403 or 429 comes back without X-Proxy-Error.

Code Meaning
407 Auth required: bad, missing, or revoked API key.
403 Plan violation: a region (or IP type) outside your org’s allow-list.
402 Out of credits (insufficient_credits).
429 Over your org’s concurrency cap or per-second rate cap (rate_limited).
502 strict=true and no node matches your constraints, or an unknown strategy name.
592–596 The node couldn’t complete the call to the target (upstream_unreachable, dns_failure, connection_refused, connection_reset, tls_error).
597 Every eligible node is at its concurrency limit for this target (governor_throttle). Retry shortly.
598 No response from the target within the timeout (upstream_timeout).
599 No node or free stream available, or the node’s stream closed (no_edge, no_stream, edge_closed).