Proxy./ docs

Errors

Errors return a non-2xx status and a JSON body with a human-readable error message plus a machine-readable code where useful.

Errors return a non-2xx status and a JSON body with a human-readable error message, a machine-readable code, and the requestId of the call (the same value as the X-Request-Id response header). Scraper input errors add a details string naming the bad field. Branch on code, not on the message text: messages get reworded, codes do not. When you write to support about a failed call, include the requestId and we can find that exact request.

400Invalid product, quantity, targeting or scraper input, or a request body the endpoint does not understand (`unknown_field`, `invalid_body`).
401Missing or invalid API key.
402Wallet balance short, or per-key daily spend cap reached.
403Key is missing the required scope, or the platform refused access to the target.
404Unknown scraper, or the target does not exist (private, deleted, wrong handle).
429Rate limited. Slow down and retry (Retry-After header).
502Transient failure fetching from the platform. Retry shortly. Never billed.
503The scraper is temporarily unavailable on our side. Retry shortly. Never billed.

Request body errors

Every write body is checked against its documented fields before anything runs. A field the endpoint does not know is refused, naming the field and the accepted set, so a typo or a guessed option can never be dropped in silence and charged for.

codeStatusDescription
unknown_field400The body carries a top-level field the endpoint does not read. The message names it and lists the accepted fields, e.g. Unknown field 'separate_plan'. This endpoint accepts: product_id, quantity, fulfillment_meta, method, expected_amount_cents. Nothing was charged. The most common case is country sent at the top level of POST /orders: a residential order carries no country at all (you choose it per line when you generate lines), and a dedicated-IP order puts it inside fulfillment_meta. See Create an order.
invalid_body400The body is not valid JSON, or a field has the wrong type. The message includes the shape the endpoint expects.
Unknown field
{
  "error": "Unknown field 'separate_plan'. This endpoint accepts: product_id, quantity, fulfillment_meta, method, expected_amount_cents.",
  "code": "unknown_field",
  "requestId": "3f2b6d9c-7a1e-4c55-9d0e-2b8a5f6c1d47"
}

Common codes

Every error on /api/v1 carries a code. These are the ones a client is most likely to branch on; endpoint-specific codes (insufficient_balance, already_applied, reseller_forbidden) are documented on their endpoints.

codeStatusDescription
unauthorized401No key, an unknown key, or a revoked one. Send X-API-Key: hpx_….
account_blocked403The acting account may not transact. Contact support.
invalid_quantity400quantity is missing, zero, negative or not a whole number. Quantities are whole GB or whole IPs; a fraction is refused rather than rounded.
missing_product400No product_id in the body. Ids come from GET /products.
unsupported_method400A payment method we do not offer. Orders take wallet or any rail; deposits take any rail: card, crypto, alipay, wechat, upi, momo, qris, pix, dana, fpx, oxxo, boleto, paymaya, grabpay_ph. The refusal names the full list.
invalid_limit, invalid_offset400A paging parameter that is not a usable number. A page size above the maximum is capped, not refused.
invalid_count, invalid_sticky400Line generation: count must be a whole number from 1 to 5000 and at most the plan's generate.maxCount, stickyMinutes a whole number of minutes, 0 or more.
invalid_asn, invalid_os, invalid_strict, invalid_exclude, invalid_udp400Line generation on Residential Premium: asn must be a whole AS number, os one of windows / android / ios / mac, strict and udp booleans, excludeAsn / excludeCountries / excludeStates / excludeCities lists of up to 20 entries.
not_found404The order, plan or webhook does not exist, or does not belong to the acting account. The two cases are deliberately indistinguishable.
price_changed409The order sent an expected_amount_cents that no longer matches the price. Nothing was charged; the body carries the current amountCents, unitPriceCents and quantity, so you can show the new total and ask your buyer again.

Gateway status codes

A generated Residential Premium line answers with its own status codes when a request cannot be served. They come from the proxy gateway, not from /api/v1, so they carry no code field; this is what each one means and what to do.

StatusMeaningDescription
407Proxy authThe username or password on the line is wrong, or the line was generated for another plan. Regenerate the line; a whitelisted IP connects without credentials.
403Bad targetingA targeting token the gateway does not accept: a state and a city together, an ISP without a country, a misspelt place. Pick places and networks from the /geo/* lists.
464Destination refusedThe target host, port or protocol is blocked by the network's usage policy.
465No IP for the targetNothing free matches the targeting right now. Widen it (drop the city or ISP), or generate with strict: false to fall back within the country.
466Plan traffic used upThe plan's GB are spent. Top up the plan; lines keep working as soon as the balance lands.
467Session traffic capThe session used up a traffic cap set for that one session. Lines generated here never set one; a username edited by hand with a -limit- token gets this once that cap is spent. Use a new session id.
568Session errorThe network's own error on one sticky session. A session can keep answering 568 after it was released, so retrying the same line does not clear it. Change the session id in the username (or generate the line again) and the next request binds a fresh IP; releasing that session once more also clears it.
5xxGateway errorRetry with backoff. Persisting errors are ours to chase: tell support the time and the line's port.

Scraper error codes

A failed scrape names its cause in code so you can handle each one differently instead of retrying everything. Nothing that fails on our side is billed — errors, timeouts and rate limits all cost nothing. The one exception is a target that does not exist: the platform was queried and answered, so that call is billed like any other, and each code below says which it is.

codeStatusDescription
target_not_found404The profile, post or ID is not there. Private, deleted, or the handle is wrong. Retrying will not help; fix the input. Billed, because the platform was queried and gave us its answer.
target_restricted403The platform refused it: age-gated, region-locked or login-only content. Retrying will not help. Not billed.
bad_input400The endpoint rejected these parameters. Check the required parameters for that endpoint. Several accept one of a pair (a handle or a user id) and reject a call carrying neither. Not billed.
provider_failed502A transient fetch failure. Safe and sensible to retry, ideally with a short backoff. Not billed.
upstream_credits_exhausted503A capacity problem on our side, not a problem with your request. Retry shortly; if it persists, contact us. Not billed.
upstream_auth_rejected503As above: ours to fix, not yours. Retry shortly and tell us if it continues. Not billed.
Error response
{
  "error": "No data found for this target. It may be private, deleted, or the handle/URL may be wrong.",
  "code": "target_not_found"
}
Changed recently
Before 2026-07-30 every failed scrape answered 502 with the same generic message, so a mistyped handle looked identical to an outage. The statuses and codes above are what the API returns now.

Need a hand wiring this up? Email support@hproxy.com. A real person reads every message.

Proxy.· developer documentation