PriceFetch returns structured errors with codes like UNSUPPORTED_RETAILER, PRICE_NOT_FOUND, and RATE_LIMITED. Each has a specific HTTP status code and a clear fix.
Every PriceFetch error response follows the same envelope structure. The `success` field is `false`, and the `error` object contains a machine-readable `code` and a human-readable `message`. Always check the `code` field for programmatic error handling — don't parse the message string.
{
"success": false,
"error": {
"code": "PRICE_NOT_FOUND",
"message": "Could not extract a price from the provided URL."
},
"request_id": "req_abc123"
}**INVALID_API_KEY (401)** — the API key in the `X-API-Key` header is missing, malformed, or doesn't match any active key. Double-check that you're sending the full key (not the prefix) and that the key hasn't been regenerated.
**INSUFFICIENT_CREDITS (402)** — your credit balance is zero. Purchase more credits from the dashboard or enable auto top-up. Failed requests (server-side errors) don't consume credits, so this means your balance is genuinely exhausted.
**VALIDATION_ERROR (400)** — the request is malformed. Usually means the `url` query parameter is missing or isn't a valid URL. Check that the URL is properly URL-encoded.
**UNSUPPORTED_RETAILER (422)** — the URL's domain isn't in PriceFetch's supported retailer list. Check the docs for supported retailers. If you're passing an affiliate redirect URL, resolve it to the actual product URL first.
**PRICE_NOT_FOUND (422)** — PriceFetch loaded the page but couldn't extract a price. Common causes: the product is discontinued, the URL points to a category page instead of a product page, or the retailer changed their page structure.
**PAGE_LOAD_FAILED (422)** — the page didn't load within the timeout window. The retailer might be down, blocking requests, or the URL might be invalid. This error does not consume credits.
**RATE_LIMITED (429)** — you've exceeded your per-second or monthly rate limit. Back off and retry. Check the `X-RateLimit-Reset` header for when you can retry.
**INTERNAL_ERROR (500)** — something went wrong on PriceFetch's end. This is rare and doesn't consume credits. Retry after a few seconds. If it persists, contact support.
Handle errors by status code category, then by error code for specific behavior. Retry on 429 and 5xx. Don't retry on 4xx — those indicate a problem with your request that won't change on retry.
import requests
import time
def fetch_price(url: str, api_key: str, max_retries: int = 3) -> dict | None:
for attempt in range(max_retries):
resp = requests.get(
"https://api.pricefetch.dev/v1/price",
params={"url": url},
headers={"X-API-Key": api_key},
timeout=30,
)
data = resp.json()
if data["success"]:
return data["data"]
code = data["error"]["code"]
# Don't retry client errors
if code in ("INVALID_API_KEY", "VALIDATION_ERROR",
"UNSUPPORTED_RETAILER", "INSUFFICIENT_CREDITS"):
raise ValueError(f"Client error: {code} — {data['error']['message']}")
# Retry on rate limit with backoff
if code == "RATE_LIMITED":
reset = int(resp.headers.get("X-RateLimit-Reset", 5))
time.sleep(reset)
continue
# Retry on server errors and transient scrape failures
if code in ("INTERNAL_ERROR", "PAGE_LOAD_FAILED"):
time.sleep(2 ** attempt)
continue
# PRICE_NOT_FOUND — product issue, don't retry
if code == "PRICE_NOT_FOUND":
return None
return None # Exhausted retriesStill stuck?
Our support team can help debug your integration.
Sign up in 30 seconds. No credit card required. One credit per successful API call.