Error Codes & Troubleshooting
WebPerception API uses standard HTTP status codes. This guide covers every error you might encounter and how to fix it.
HTTP Status Codes
| Code | Name | Description |
|---|---|---|
| 200 | OK | Request succeeded. Response contains your data. |
| 400 | Bad Request | Invalid parameters. Check the error field for details. |
| 401 | Unauthorized | Missing or invalid API key. |
| 403 | Forbidden | Valid API key but insufficient permissions or plan limits. |
| 404 | Not Found | The target URL returned a 404 or the endpoint doesn't exist. |
| 422 | Unprocessable | Valid request but the target page couldn't be processed (e.g., CAPTCHA, login wall). |
| 429 | Rate Limited | Too many requests. Slow down or upgrade your plan. |
| 500 | Server Error | Something went wrong on our end. Retry with exponential backoff. |
| 502 | Bad Gateway | Upstream timeout. The target site took too long to respond. |
| 503 | Service Unavailable | Temporary maintenance. Retry after a few seconds. |
Common Issues
401 — "Invalid API Key"
Your API key is missing, malformed, or revoked.
Fix:
- Check that you're sending the key in the
Authorization: Bearer YOUR_API_KEYheader - Verify the key in your dashboard
- Make sure there are no extra spaces or newlines in the key
- If using environment variables, confirm they're loaded:
echo $MANTIS_API_KEY
# ✅ Correct
curl -X POST https://api.mantisapi.com/v1/scrape \
-H "Authorization: Bearer sk_live_abc123..." \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
# ❌ Wrong — missing "Bearer" prefix
curl -X POST https://api.mantisapi.com/v1/scrape \
-H "Authorization: sk_live_abc123..."
429 — Rate Limited
You've exceeded your plan's requests-per-second limit.
💡 Tip: Check the
Retry-After header in the response — it tells you exactly how many seconds to wait.
Implement exponential backoff:
import time
import requests
def scrape_with_retry(url, api_key, max_retries=3):
for attempt in range(max_retries):
response = requests.post(
"https://api.mantisapi.com/v1/scrape",
headers={"Authorization": f"Bearer {api_key}"},
json={"url": url}
)
if response.status_code == 429:
wait = int(response.headers.get("Retry-After", 2 ** attempt))
print(f"Rate limited. Waiting {wait}s...")
time.sleep(wait)
continue
return response
raise Exception("Max retries exceeded")
422 — Page Can't Be Processed
The target page loaded but couldn't be scraped. Common causes:
- CAPTCHA: The site is showing a CAPTCHA challenge. Try enabling
"render_js": trueand"proxy_country": "US" - Login wall: The page requires authentication. WebPerception can't bypass login pages.
- Empty page: JavaScript-heavy SPA that needs more time. Use
"wait_for": "selector"with a CSS selector.
502 — Target Site Timeout
The website you're scraping took too long to respond (>30 seconds).
Fix:
- Check if the target site is actually online
- Try without
"render_js": true— JS rendering adds time - Some sites are slow during peak hours — retry later
Empty or Unexpected Content
You got a 200 response but the content isn't what you expected.
⚠️ Common cause: The page requires JavaScript rendering but you didn't enable it. Add
"render_js": true to your request.
# Many modern sites need JS rendering
response = requests.post(
"https://api.mantisapi.com/v1/scrape",
headers={"Authorization": f"Bearer {api_key}"},
json={
"url": "https://example.com/dynamic-page",
"render_js": True,
"wait_for": ".product-card" # Wait for this element
}
)
AI Extraction Errors
Extraction Returns Empty or Wrong Data
- Schema too complex: Simplify your extraction schema. Start with 2-3 fields, then add more.
- Ambiguous field names: Use descriptive names.
"product_price_usd"works better than"price". - Wrong page content: Make sure the URL actually contains the data you're extracting. Use
/scrapefirst to verify.
💡 Pro tip: Always test your extraction schema on a single page before running it at scale. Use the
/scrape endpoint first to see what content the AI model receives.
Credit Usage
| Endpoint | Standard | With JS Rendering |
|---|---|---|
/scrape | 1 credit | 2 credits |
/screenshot | 1 credit | 2 credits |
/extract | 2 credits | 3 credits |
Failed requests are not charged. If a request returns a 4xx or 5xx error, no credits are deducted from your account.