ScreenshotMachine CLI returns a 403 error: what to check
A 403 alone does not reveal why ScreenshotMachine rejected a CLI request. Capture the full response, then check the endpoint, parameters, key, URL, and hash.
A 403 response by itself does not identify why a ScreenshotMachine CLI request failed. Screenshot Machine’s published API documentation lists provider error codes but does not map any of them to HTTP 403. First capture the complete response—including headers and body—and determine whether the status came from Screenshot Machine, an intermediary, or the target page. Then compare the CLI’s actual request with the documented GET format: the API endpoint, customer key, target URL, URL encoding, and, if configured, the URL hash.
This guide covers ScreenshotMachine-specific checks based on its official API documentation. A provider error code or account-specific response may be needed to identify the cause of a particular 403.
1. Capture the full response before changing the request
Save the HTTP status, response headers, and response body. Screenshot Machine says its error responses include X-Screenshotmachine-Response, which carries a specific error code. That provider signal is more useful than guessing from the HTTP status alone.
curl --silent --show-error --include --get \
'https://api.screenshotmachine.com/' \
--data-urlencode 'key=YOUR_CUSTOMER_KEY' \
--data-urlencode 'url=https://example.com/' \
--output response.body
--include prints the response headers along with the response; --output saves the body separately. Depending on the response and curl version, headers and body may both appear on standard output when using --include. For a clean separation, save headers to a file:
curl --silent --show-error --get \
'https://api.screenshotmachine.com/' \
--data-urlencode 'key=YOUR_CUSTOMER_KEY' \
--data-urlencode 'url=https://example.com/' \
--dump-header response.headers \
--output response.body \
--write-out '\nHTTP %{http_code}\n'
Inspect response.headers for X-Screenshotmachine-Response, and inspect response.body without assuming it is a screenshot. If the request uses a real key, do not paste the command, headers, or logs into a public issue without redacting the key and any secret-derived values.
2. Check the documented request format
Screenshot Machine documents an HTTP GET request to https://api.screenshotmachine.com/. Its required parameters are the customer key and target url. Compare the request the CLI actually sent—not only its configuration file—with that format.
- Endpoint and method: confirm the hostname is
api.screenshotmachine.com, the path is/, and the request method is GET. - Key: confirm a nonempty customer key is sent under the documented
keyparameter. - Target URL: confirm a nonempty URL is sent under
url. Include its scheme, such ashttps://. - Encoding: encode query values correctly. Use a query-building library or curl’s
--data-urlencode; hand-concatenating a URL can break on ampersands, spaces, fragments, or other reserved characters. - Secret phrase: if one is configured on the account, confirm the request includes the matching
hashfor the exact URL value sent.
A minimal request in the vendor’s documented style is:
curl --get 'https://api.screenshotmachine.com/' \
--data-urlencode 'key=YOUR_CUSTOMER_KEY' \
--data-urlencode 'url=https://example.com/'
Use the current vendor documentation for any additional capture options your CLI supplies. Do not add parameters as a way to troubleshoot a 403 unless the provider’s returned error or your intended capture requires them.
3. Read the provider error code
The official error table lists these codes: invalid_hash, invalid_key, invalid_url, missing_key, missing_url, no_credits, invalid_selector, invalid_crop, and system_error. It does not state that any of them corresponds to HTTP 403.
| Provider code | What to check |
|---|---|
missing_key |
Whether the request includes the required key parameter and whether the CLI is reading the intended configuration or environment variable. |
invalid_key |
Whether the key is copied correctly and belongs to the account you intend to use. Avoid sharing the key while asking for help. |
missing_url |
Whether the request includes a nonempty url parameter. |
invalid_url |
Whether the target value is a valid, correctly encoded URL, including its scheme. |
invalid_hash |
If an account secret phrase is configured, whether the hash was made from the exact URL value and matching secret phrase, following the vendor’s current instructions. |
no_credits |
Whether the account has credits remaining. The documentation lists this error but does not associate it with HTTP 403. |
invalid_selector or invalid_crop |
Whether selector or crop options in the request are valid for the capture you want. |
system_error |
Preserve the response details and consult the provider’s support or current guidance; the code alone does not identify a local CLI fix. |
If X-Screenshotmachine-Response is absent, that does not prove which component generated the 403. The response could have come from an intermediary, or another layer in the request path. Keep the response intact and investigate its origin before changing account or target-site settings.
4. Verify a secret phrase and hash carefully
Screenshot Machine documents an optional secret phrase. When one is set, the request must include a matching hash. The documentation describes the hash as MD5 calculated from the URL parameter value concatenated with the secret phrase. The URL used for the hash must match the URL value sent in the request exactly.
- Check for differences in scheme, hostname, path, query string, trailing slash, and percent encoding.
- Use the provider’s current documentation to confirm the precise hash input and parameter format for your account.
- Do not put the secret phrase in a shared command transcript, shell history, public log, or support request.
- Do not assume a bad hash caused the 403 unless the provider error signal or account configuration supports that conclusion.
Because MD5 here is a vendor-required request-signing mechanism, follow Screenshot Machine’s documented format rather than substituting a different hash. Keep the secret phrase private.
5. Distinguish an API rejection from a target-page or intermediary response
A 403 can be observed at different points in a request flow. The available Screenshot Machine documentation does not specify how every target page’s own 403 is represented by every CLI. Use the saved headers and body to establish what actually responded:
- If the response includes Screenshot Machine’s error header, compare its value with the provider’s error table.
- If the response does not carry the provider signal, inspect the response body and other headers and check whether a proxy, gateway, firewall, or other intermediary returned it.
- If the API call succeeds but the captured page itself displays an access-denied response, treat that as a target-page result and investigate the page’s access rules separately.
Do not label a target-site restriction as an API-key problem, or an API rejection as a target-site block, without evidence from the response.
6. Check credits as a separate account check
The vendor lists no_credits as an error code. Check the account’s credit balance if the provider response points to it or the account may be depleted. The published documentation does not map exhausted credits to HTTP 403, so a low or empty balance should not be presented as the cause of a 403 without a matching provider response.
Common causes and fixes
| Observation | Likely next check | Action |
|---|---|---|
403 with missing_key or invalid_key |
The key parameter or account key | Confirm the CLI sends the intended key under key; check for whitespace, a stale value, or the wrong account. |
403 with missing_url or invalid_url |
The target URL parameter | Pass a complete URL and encode it as a query value rather than concatenating raw text. |
403 with invalid_hash |
Secret phrase and exact URL value | Recompute the hash using the vendor’s documented input for the exact URL sent; keep the phrase private. |
403 with no_credits |
Account credit balance | Check account credits. The code indicates the relevant account condition; the docs do not define it as an HTTP 403 mapping. |
403 without X-Screenshotmachine-Response |
Response origin | Save the body and all headers; determine whether an intermediary or another layer returned the status. |
| API response is successful, but the screenshot shows an access-denied page | Target page’s access policy | Inspect the captured page result and its access requirements; do not change API credentials based on the page image alone. |
Performance, reliability, and cost considerations
This is a request-diagnosis problem, so repeated retries with an unchanged request are unlikely to provide new information. Capture one complete response, correct a specific confirmed request issue, and retry. If the provider reports a transient system error, preserve its code and details and follow the vendor’s current support guidance.
Do not expose customer keys or secret phrases in verbose command output shared with others. For automated troubleshooting, record the HTTP status, provider error header, and a redacted response body, while keeping credentials out of logs. Check account credits independently when relevant; do not infer billing or credit behavior from the HTTP status alone.
Or skip the browser setup
If the goal is to get a website screenshot rather than debug this particular ScreenshotMachine request, ScreenshotNeo offers a one-call screenshot API and an MCP server for AI agents. Its API docs are at screenshotneo.com/docs.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
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)
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 removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up free and try ScreenshotNeo.
FAQ
Does a 403 mean my ScreenshotMachine key is invalid?
No. The status alone does not identify the cause. Check X-Screenshotmachine-Response and the full response before diagnosing the key.
Does Screenshot Machine document a 403 mapping for its error codes?
The official error table lists provider codes but does not specify HTTP 403 as the status for any of them.
Could having no credits cause this 403?
The vendor lists no_credits, but its documentation does not associate that code with HTTP 403. Check the provider’s error signal and account state.
What should I send support if the cause is still unclear?
Provide the timestamp, HTTP status, redacted response headers and body, and the value of X-Screenshotmachine-Response if present. Never include a live key or secret phrase.


