ScrapingAnt SDK errors: Python v2 and JavaScript v1
Start with your installed package version and the endpoint it calls. The mappings here were verified on October 9, 2026 against Python scrapingant-client source version 2.1.0 and JavaScript @scrapingant/scrapingant-client source version 0.2.1. Source versions are not a claim about the latest package-registry release or every older installation.
python -m pip show scrapingant-client
npm ls @scrapingant/scrapingant-client
Python 2.1.0 uses /v2/extended for general_request and /v2/markdown for markdown_request. JavaScript 0.2.1 uses POST /v1/general, with configuration in a JSON body. Do not copy that body format into a direct v2 call; v2 uses query parameters and forwards its body to the target. See v1 reference, v2 reference and API error diagnosis.
Python exceptions and masked API errors
The client maps the outer API HTTP status, not the target's status_code, to an exception. The exact exception messages below are SDK wording and may replace the API's detail.
| Outer status or failure | Python exception and exact wording | Diagnosis and next action |
|---|---|---|
403 | ScrapingantInvalidTokenException: API token is wrong or you have exceeded the API calls request limit | Also masks IP restrictions. Check the three API 403 causes; do not assume the key is invalid. |
404 | ScrapingantSiteNotReachableException: The requested URL is not reachable ({url}) | Template: {url} is your supplied target. Check reachability and worker timeout; redact private URL values. |
422 | ScrapingantInvalidInputException | Its argument is the decoded response object; str(error) is its Python representation, not a new API code. Read error.args[0]['detail'] locally; fix the named parameter. |
423 | ScrapingantDetectedException: The anti-bot detection system has detected the request. Please, retry or change the request settings. | Follow target-site detection guidance. |
500 | ScrapingantInternalException: Something went wrong with the server side. Please try later or contact support | Masks API/AI/Markdown 500 variants. Check the endpoint; follow server error guidance. |
Synchronous requests.exceptions.Timeout or asynchronous httpx.TimeoutException | ScrapingantTimeoutException: Got timeout while communicating with Scrapingant servers. Check your network connection. Please try later or contact support | A client-to-API timeout, not the API's worker-timeout 404. Check connectivity and client timing; decide whether the operation is safe to repeat. |
Python 2.1.0 has no dedicated 409 mapping. A 409 JSON error passed through general_request reaches the success parser and raises KeyError: 'html'; markdown_request can instead fail on missing url. Other unmapped non-success statuses can also reach parsing. An HTML or non-JSON gateway response can raise a JSON decoding exception before status mapping. These failures do not prove the target HTML is malformed.
If you see KeyError: 'html', inspect the actual API status/body in a controlled, sanitized HTTP diagnostic; check free-plan concurrency first. If you need reliable handling of every HTTP status, use a direct HTTP client that checks status before success parsing. Do not call private SDK methods as an application workaround, dump the session headers or publish an exception's entire response.
The inspected Python implementation has no automatic retry loop. Its asynchronous HTTP client sets a 120-second timeout; its synchronous call does not pass a timeout to requests.Session.request. A synchronous Requests timeout can still be translated if a customized transport raises one. Do not assume both methods enforce the same deadline, or pass timeout to general_request as if it were a supported SDK argument. Check the API timeout parameter separately.
Reproduce a Python 422 without an API call
Install the matching package in your own environment with python -m pip install 'scrapingant-client==2.1.0'. This example mocks the session; it sends no HTTP traffic and uses a dummy token. It tests exception handling, not provider availability.
from unittest.mock import Mock, patch
from scrapingant_client import ScrapingAntClient, ScrapingantInvalidInputException
client = ScrapingAntClient(token="offline-placeholder")
detail = "Wrong host part of url. Please check out the documentation: https://docs.scrapingant.com/"
response = Mock(status_code=422)
response.json.return_value = {"detail": detail}
with patch.object(client.requests_session, "request", return_value=response) as request:
try:
client.general_request("bad_url")
except ScrapingantInvalidInputException as error:
assert error.args[0]["detail"] == detail
print(type(error).__name__)
else:
raise AssertionError("Expected a validation exception")
assert request.call_count == 1
Verified offline output: ScrapingantInvalidInputException. After correcting a real request, check both the target result.status_code and useful result.content; the target status is not the outer API status.
JavaScript ScrapingAntApiError and transport errors
JavaScript 0.2.1 wraps an HTTP failure in ScrapingAntApiError. error.statusCode is the outer API status, error.httpMethod is the API method, and error.message uses the API's detail when present. There is no separate numeric ScrapingAnt code on this wrapper. Map 403/404/409/422/423/500 through the API error reference, remembering that this SDK calls v1.
If a response has data but no detail, its message is the template Unexpected error: {serialized_response_data}. That fallback may include private content; inspect locally and sanitize it. A network Axios error with no response is rethrown as a transport error rather than this API wrapper. There is no single verified ScrapingAnt message/code for every DNS, TLS or network timeout; inspect the original error and whether a response exists.
Default options are maxRetries: 8, minDelayBetweenRetriesMillis: 500 and timeoutSecs: 60. The implementation retries network errors and HTTP statuses 500 or higher; it stops on 4xx, including 409 and 423. maxRetries counts additional attempts, so the default permits up to nine attempts. Set maxRetries: 0 when diagnosing a single attempt or when repetition would be unsafe. Avoid multiplying SDK attempts with an outer retry loop; follow safe retry guidance.
Reproduce a JavaScript API error without an API call
Install the matching package with npm install @scrapingant/scrapingant-client@0.2.1. This fixture replaces the internal HTTP transport solely for an offline test. That internal shape is version-specific and is not an application API to depend on.
const assert = require('node:assert/strict');
const ScrapingAntClient = require('@scrapingant/scrapingant-client');
const client = new ScrapingAntClient({ apiKey: 'offline-placeholder', maxRetries: 0 });
const detail = 'Wrong host part of url. Please check out the documentation: https://docs.scrapingant.com/';
let attempts = 0;
client.scrapingClient.httpClient.axios.request = async config => {
attempts += 1;
throw {
isAxiosError: true,
response: { status: 422, data: { detail }, config }
};
};
(async () => {
await assert.rejects(client.scrape('bad_url'), error => {
assert.equal(error.name, 'ScrapingAntApiError');
assert.equal(error.statusCode, 422);
assert.equal(error.httpMethod, 'post');
assert.equal(error.message, detail);
console.log(error.name, error.statusCode);
return true;
});
assert.equal(attempts, 1);
})().catch(() => { process.exitCode = 1; });
Verified offline output: ScrapingAntApiError 422. This test does not send a live provider request. For successful SDK calls, inspect both the returned target status_code and content rather than assuming resolved means the target accepted the request.
Version checks and support
Compare your installed version with the inspected versions before applying a workaround. Python and JavaScript package version numbers are independent of API version numbers. A page viewed in the v2 documentation does not change the JavaScript SDK's v1 endpoint. For direct v2 JavaScript requests, follow request/response format; do not invent a v2 SDK option.
Sources: Python exceptions, Python status handling, JavaScript wrapper, JavaScript retry logic and JavaScript endpoint.
For persistent failures, use the sanitized support checklist. These wrappers do not expose a request ID. Include the actual package/API version and timestamp; never publish API keys, cookies, private URLs or complete Axios/session dumps in an SDK GitHub issue.