Error codes

Every status the gateway returns, and what to do about each.

Errors raised by the gateway carry an x-wproxy-error header with a stable machine-readable code. Errors from the target site pass through untouched, so a 403 with no wproxy header came from the target, not from us.

Gateway errors

StatusCodeMeaningAction
400malformed_usernameA targeting flag could not be parsedCheck for stray hyphens inside flag values
400city_without_country-city- used with no -country-Add the country flag
402insufficient_balanceBalance or plan allowance exhaustedTop up, or raise the spend limit
403flag_not_permittedSub-user is restricted from that country or productWiden the sub-user's allow list
407bad_credentialsUsername or password rejectedVerify the pair; check the sub-user is enabled
429concurrency_exceededToo many simultaneous connectionsLower concurrency or raise the ceiling
502exit_failedThe exit dropped mid-requestRetry; this is credited automatically
503no_exit_availableNo exit matched with -strict setLoosen targeting or drop -strict
504exit_timeoutThe target did not respond in timeRaise your timeout or retry

5xx from us is free

Any request that fails inside our infrastructure — 502, 503, 504 with an x-wproxy-error header — is credited back automatically and appears as an adjustment line on the invoice. You never pay for our failures.

A retry policy that behaves

python
import time, requests

RETRYABLE = {429, 502, 503, 504}

def get(url, proxies, attempts=4):
    for i in range(attempts):
        try:
            r = requests.get(url, proxies=proxies, timeout=30)
            if r.status_code not in RETRYABLE:
                return r
        except requests.RequestException:
            pass
        time.sleep(min(2 ** i, 8))   # 1s, 2s, 4s, 8s
    raise RuntimeError(f"gave up on {url}")

Do not retry 402, 403 or 407

They are configuration problems, not transient faults. Retrying them wastes time and, in the case of 407, can trip our own brute-force protection.

Something inaccurate?Tell support