ScreenshotAPI.net 403 Error When Capturing a Website: How to Fix It
A ScreenshotAPI.net 403 can mean an exhausted quota, an expired trial, or a refused target connection. Find the returned error code and use the matching fix.
A ScreenshotAPI.net 403 does not point to one universal problem. The service documents several different errors with that status: screenshots_limit_reached, trial_expired, and ERR_CONNECTION_REFUSED. Read the error code and message in the response first; then determine whether the issue is your account or the target site’s reachability. A plan change can address a quota or expired trial, but it does not establish that a target website will allow a capture.
1. Identify which 403 you received
Save the complete response body and HTTP status from the failed request. The status alone is insufficient: the documented 403 cases have different causes and fixes.
| Returned code | What it indicates | First action |
|---|---|---|
screenshots_limit_reached |
The account’s screenshot quota has been exceeded. | Check usage and the plan quota. If you need more captures, ScreenshotAPI.net’s Help page recommends upgrading to a plan with a higher quota. |
trial_expired |
The trial period has ended. | Check the account’s trial and subscription status, then upgrade as the error reference directs. |
ERR_CONNECTION_REFUSED |
The connection to the target server was refused. The vendor lists network issues, server availability, or a firewall as possible causes. | Check that the target is reachable and investigate network or firewall restrictions before changing your plan. |
These descriptions come from ScreenshotAPI.net’s own [error reference](https://www.screenshotapi.net/docs/errors). They describe the service’s error codes; they do not by themselves prove the root cause of an individual failed capture.
2. Capture the response safely
Use a small diagnostic request that records the HTTP status, response headers, and body. Do not log or publish your API token. Keep the target URL encoded as a query parameter.
cURL
curl --silent --show-error \
--get 'https://shot.screenshotapi.net/v3/screenshot' \
--data-urlencode 'token=YOUR_API_KEY' \
--data-urlencode 'url=https://example.com' \
--dump-header response-headers.txt \
--output response-body.bin \
--write-out '\nHTTP %{http_code}\n'
On success, the endpoint returns the requested capture, so response-body.bin may be an image or another requested output. On an error, inspect the body for the service’s code and message. Avoid treating every saved response as an image.
Python
import requests
endpoint = "https://shot.screenshotapi.net/v3/screenshot"
params = {
"token": "YOUR_API_KEY",
"url": "https://example.com",
"file_type": "png",
"output": "image",
}
response = requests.get(endpoint, params=params, timeout=90)
print("HTTP", response.status_code)
print("Content-Type:", response.headers.get("content-type"))
if response.ok:
with open("screenshot.png", "wb") as image_file:
image_file.write(response.content)
else:
print(response.text)
Node.js
const params = new URLSearchParams({
token: 'YOUR_API_KEY',
url: 'https://example.com',
file_type: 'png',
output: 'image',
});
const response = await fetch(
`https://shot.screenshotapi.net/v3/screenshot?${params}`
);
console.log('HTTP', response.status);
console.log('Content-Type:', response.headers.get('content-type'));
if (response.ok) {
const image = Buffer.from(await response.arrayBuffer());
await (await import('node:fs/promises')).writeFile('screenshot.png', image);
} else {
console.error(await response.text());
}
These examples use the documented v3 render endpoint and its token and url parameters. See [Render a Screenshot](https://www.screenshotapi.net/docs/renderScreenshot) for the request reference.
3. Fix the matching cause
If the code is screenshots_limit_reached
- Confirm that the response contains this exact code rather than another 403.
- Check the account’s current usage and quota in its dashboard.
- If the quota is exhausted and more captures are required, follow the vendor’s documented upgrade path. The [Help page](https://www.screenshotapi.net/help) recommends a plan with a higher screenshot quota.
- If the account dashboard does not appear to match the error, retain the response and request details when contacting the vendor’s support.
Do not troubleshoot proxies or target headers as the first response to a quota error: the documented cause is account usage.
If the code is trial_expired
- Check whether the account is still on a trial and whether it has expired.
- Check the account’s plan or billing status.
- Upgrade or restore an eligible account as directed by the [error reference](https://www.screenshotapi.net/docs/errors), then retry with the same target and options.
A target-site network change does not address an expired trial. If the account appears active but the response persists, provide the exact error code and request time to support.
If the code is ERR_CONNECTION_REFUSED
- Open the target URL from a normal browser or another network and confirm it is available. Check for an outage, a changed URL, or a redirect to an inaccessible host.
- Check whether the target is restricted by a firewall, IP allowlist, network policy, or regional access rule. A refusal can occur before the page is rendered.
- Verify that the URL is public and reachable from the capture service’s network. A page available only from your local machine or private network may not be reachable by a remote renderer.
- If the target’s policy permits it, test a documented request-context or routing option, such as a custom header, user agent, or proxy. Change one setting at a time and compare the response.
ScreenshotAPI.net documents headers, user_agent, and proxy as request options in its [browser environment emulation documentation](https://www.screenshotapi.net/docs/browserEnvironmentEmulation). A proxy can change routing, and headers or a user agent can change the request context. These are diagnostic options, not guaranteed ways to resolve a refusal or bypass a site’s access controls. Use only routing and request settings you are authorized to use.
4. Rule out request construction errors
Before experimenting with target access settings, make sure the request itself is valid:
- Use the documented v3 endpoint:
https://shot.screenshotapi.net/v3/screenshot. - Provide the API key as
tokenand the target asurl. Parameter names are case-sensitive. - Pass a complete target URL beginning with
https://. The vendor’s [Help page](https://www.screenshotapi.net/help) notes that a missing or misnamed URL parameter can causeurl_requiredand says the URL should start with HTTPS. - URL-encode the target rather than manually concatenating an unescaped URL into the query string. This matters when the target itself contains
&, query parameters, or other reserved characters. - Keep the token private. Send it in server-side requests and do not place it in client-side code or public logs.
An invalid or missing URL is documented as a 400-class error, rather than one of the 403 causes described above. Correcting request construction is still a useful check, but it will not replenish quota, renew a trial, or make an unreachable target available.
5. Troubleshooting checklist
| Symptom | Likely path | Next step |
|---|---|---|
403 with screenshots_limit_reached |
Quota or usage entitlement | Check usage and plan quota; upgrade if more capacity is needed. |
403 with trial_expired |
Trial or account status | Check account eligibility and upgrade as directed. |
403 with ERR_CONNECTION_REFUSED |
Target availability, network, or firewall | Test reachability, then investigate permitted routing or request-context settings. |
url_required or another URL validation error |
Missing, misnamed, malformed, or unencoded URL parameter | Use the exact url parameter with a complete HTTPS URL and encode it. |
| Only a particular target fails | Target-specific reachability or access policy | Compare with a known public page; inspect the target’s availability and restrictions. |
| Failures begin after changing proxy or headers | Invalid option or unintended request route | Revert the latest change, verify its format, then test one option at a time. |
6. Reliability, performance, and cost considerations
For recurring jobs, record the status, returned error code, target URL, capture options, and time of each attempt. Redact the API token and sensitive query values. This history helps distinguish a plan limit from a target outage and shows whether failures began after a configuration change.
- Retrying: Do not rapidly retry quota exhaustion or an expired trial; neither is a transient target failure. For a refused connection, a limited retry after checking target availability can help identify a temporary outage, but repeated retries cannot fix a persistent firewall rule or access policy.
- Request load: Avoid unbounded retry loops. They add load and make it harder to tell whether a later response reflects a changed condition.
- Cost: Check the plan quota before scheduling bulk or frequent captures. The vendor’s Help page describes quota-related errors and recommends upgrading for a higher quota; an upgrade addresses account capacity, not target reachability.
- Diagnostic control: When testing headers, user agents, or proxies, hold the URL and other options constant. A one-variable-at-a-time comparison makes the result easier to interpret.
7. Or skip the browser setup
If you need a screenshot endpoint under your own application’s control, [ScreenshotNeo](https://screenshotneo.com) is a website screenshot API and MCP server. The one-call request below returns the capture for the target URL. See the [ScreenshotNeo API docs](https://screenshotneo.com/docs/) for setup and options.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo accepts cookie and consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. These features do not guarantee access to every target site. Sign up for 1,000 free screenshots a month, with no card.
8. FAQ
Does every ScreenshotAPI.net 403 mean the website blocked the screenshot?
No. The documented 403 codes also include quota exhaustion and an expired trial. Identify the returned code before diagnosing target blocking.
Will upgrading fix ERR_CONNECTION_REFUSED?
The error reference describes that code as a refused connection to the target. An account upgrade is not documented as a fix for target reachability or firewall restrictions.
Can a proxy or custom user agent guarantee a successful capture?
No. The vendor documents these as request and routing options, but does not guarantee that they resolve a particular refusal. A target’s policies and network conditions still apply.
What should I send support?
Provide the timestamp, HTTP status, exact error code and message, endpoint and non-secret options, and whether the target is reachable from a normal browser. Remove the API token and any private query data.


