ScreenshotNeo

BlogHow-to

GrabzIt Screenshot API Returns 403: How to Fix It

A 403 can come from GrabzIt or the page being captured. Identify which system denied the request, then check the matching credentials and access controls.

By the ScreenshotNeo team4 October 20267 min read

A 403 response from a GrabzIt screenshot request does not identify its cause by itself. It may mean GrabzIt rejected the API request, or that the website being captured denied access. First record the response body, content type, and headers, then determine which system produced the response. For a REST request, check the application key, request formatting, and any source-IP restrictions. For the JavaScript API, check authorized domains. If the API request succeeds but the captured page is denied, investigate that page’s authentication and access rules.

GrabzIt’s documentation does not define one universal cause for every 403. The response and request path are the evidence to follow.

1. Identify where the 403 comes from

Before changing credentials or capture settings, save the exact endpoint, method, status, response headers, content type, and response body. The response body can help distinguish a GrabzIt API error from a denial at the target site. GrabzIt says REST API request errors may be returned as JSON; check the content type and inspect the response rather than treating the status code alone as a diagnosis. GrabzIt REST API documentation

What you observe Likely layer to investigate
The request to GrabzIt’s API endpoint returns 403 API credentials, request construction, or account access controls
The API request is accepted, but the capture result shows a target denial The destination page’s authentication or access controls
A browser-based JavaScript integration fails on a particular site Whether that site’s origin is authorized in GrabzIt account settings

These are diagnostic directions, not a guaranteed mapping of every response to a cause. If the evidence is unclear, retain the sanitized response and ask GrabzIt support to identify which layer returned it.

2. Fix REST API request problems

For server-side REST requests, verify that the application key belongs to the intended account and is passed using a documented authentication method. The REST reference describes using the application key as a parameter or using an Authorization Bearer header. It also warns against putting the key in client-side code because that exposes it. REST API reference

Example request with cURL

This example shows a server-side request using an application key parameter. Use the endpoint and parameter names from the current GrabzIt API reference for the capture operation you are calling; do not paste a real key into a public script or repository.

curl -G "YOUR_GRABZIT_REST_ENDPOINT" \
  --data-urlencode "key=YOUR_APPLICATION_KEY" \
  --data-urlencode "url=https://example.com" \
  -H "Accept: application/json" \
  -o response.json \
  -w "HTTP %{http_code}\n"

Replace the endpoint and parameters with those required by the specific REST operation in GrabzIt’s reference. The key parameter name and capture options depend on the API operation; this diagnostic template is not a substitute for that operation’s documented request schema. Inspect response.json and the printed status. Do not publish the response if it contains secrets.

Example request with Python

import os
import requests

endpoint = os.environ["GRABZIT_REST_ENDPOINT"]
params = {
    "key": os.environ["GRABZIT_APPLICATION_KEY"],
    "url": "https://example.com",
}
response = requests.get(endpoint, params=params, timeout=60)
print("status:", response.status_code)
print("content-type:", response.headers.get("content-type"))
print(response.text[:4000])

Set GRABZIT_REST_ENDPOINT to the documented endpoint for the operation and adapt the parameter names to its schema. Using a parameter mapping lets the HTTP library encode the target URL and its query string. If the API call is meant to submit HTML, GrabzIt’s REST reference specifies a POST request with a form-encoded body; use that documented method instead of sending the HTML as a GET parameter.

Example request with Node.js

const endpoint = process.env.GRABZIT_REST_ENDPOINT;
const key = process.env.GRABZIT_APPLICATION_KEY;

if (!endpoint || !key) {
  throw new Error('Set GRABZIT_REST_ENDPOINT and GRABZIT_APPLICATION_KEY');
}

const url = new URL(endpoint);
url.searchParams.set('key', key);
url.searchParams.set('url', 'https://example.com');

const response = await fetch(url, {
  headers: { Accept: 'application/json' },
  signal: AbortSignal.timeout(60_000),
});
console.log('status:', response.status);
console.log('content-type:', response.headers.get('content-type'));
console.log((await response.text()).slice(0, 4000));

As with the cURL and Python examples, use the actual operation endpoint and parameter names from GrabzIt’s REST reference. Keep the application key in a server-side environment variable. Do not ship it in browser JavaScript.

Request-construction checklist

  • Confirm the key belongs to the account and environment you intend to use.
  • Use the authentication method and parameter names specified for the operation.
  • Encode parameter values, especially target URLs containing their own query parameters, ampersands, or other special characters.
  • Use POST with the documented form-encoded body when submitting HTML.
  • Keep REST credentials on your server. A key embedded in client-side code can be copied and misused.

3. Check source-IP restrictions for REST calls

GrabzIt documents an account setting for authorizing the IP addresses permitted to access the API. If that restriction is enabled, compare its allowed addresses with the actual outbound IP of the machine or hosting environment making the request. Deployments, serverless functions, proxies, and hosting changes can alter the address the API sees, so check from the same environment that sends the failing request. A mismatch is a relevant configuration check; the reviewed documentation does not say that every mismatch necessarily produces HTTP 403. GrabzIt account security documentation

4. Check authorized domains for JavaScript API calls

If the integration runs in browser JavaScript, check the authorized domains in the GrabzIt account. GrabzIt says the JavaScript API will not work when no authorized domains are configured. Confirm that the origin where the code runs is authorized, including the hostname used in production, staging, or local development. The need to compare each deployed origin follows from the documented domain restriction. GrabzIt JavaScript API documentation

Do not diagnose a server-side REST request using the browser-domain setting: the relevant restriction depends on which API path your application uses.

5. If the destination page returns 403

If GrabzIt accepts the request but the page capture is denied, investigate the destination’s access requirements. Test whether the page needs login, HTTP Basic Authentication, or another supported session flow. GrabzIt documents URL-encoded username and password credentials for HTTP Basic Authentication and support for capturing pages behind session-based login walls. This does not guarantee access to pages protected by other authorization systems, identity checks, or anti-bot controls. GrabzIt documentation on capturing pages behind login

Encode both username and password when credentials are included in a URL, and avoid putting secrets in logs or public links. Prefer a dedicated account with only the access required for the capture, where that is available.

A customer-provided HTTP proxy may be relevant if the capture needs to traverse a particular network path or proxy controlled by your organization. GrabzIt documents proxy configuration, but does not present a proxy as a general solution for 403 responses. GrabzIt proxy documentation

6. Troubleshoot by symptom

Symptom Possible cause What to check
REST endpoint returns 403 and a JSON body API-level rejection or account access restriction Read the error body; verify the application key, authentication method, request schema, and source-IP authorization.
REST call works from one host but not another The second host may use a different outbound IP or credentials Compare environment variables and the actual egress address with account IP settings.
JavaScript API works on one origin but not another The failing origin may not be authorized Check the exact origin in the account’s authorized-domain settings.
API request succeeds but captured content is an access-denied page The destination page denied the capture request Check target authentication and access rules; use a supported login method if applicable.
Requests containing query strings fail or behave unexpectedly Parameters may not be correctly encoded Use a URL builder or parameter encoder rather than concatenating query strings by hand.
HTML submission does not work as expected Wrong HTTP method or body format Use POST and the documented form-encoded body for the HTML conversion operation.
A proxy change does not resolve the denial The 403 may be unrelated to network routing Re-check the response origin and target authentication; proxy support is conditional, not a general bypass.

7. Send support a useful report

If the checks do not explain the error, provide enough information to locate the failing layer without exposing credentials:

  • Timestamp and timezone, endpoint, and HTTP method.
  • Sanitized request parameters and the target URL, with private query values removed.
  • Status, response content type, relevant headers, and response body.
  • Whether the same target is accessible in a normal browser and whether the API request works from another environment.
  • Whether the integration uses REST or browser JavaScript, and whether source-IP or authorized-domain restrictions are configured.

Redact the application key, passwords, authorization headers, session cookies, and other secrets. A dated community post describes one specific 403 incident that support associated with a CDN lockdown; that example does not establish a general cause for other failures. GrabzIt community

8. Or skip the browser setup

If your goal is simply to get a website screenshot and you do not need to debug a GrabzIt integration, ScreenshotNeo is a website screenshot API and MCP server. Its one-call API returns an image or PDF:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request options. Cookie banners are accepted and removed before capture, along with known newsletter popups and chat widgets. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents use the take_screenshot, get_page_info, and capture_pdf tools. The free plan includes 1,000 screenshots a month without a card; paid plans start at $5 for 3,000 screenshots. Each response reports the page verdict and billing status in headers.

Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Does every 403 mean my GrabzIt application key is wrong?

No. The 403 may come from the API request or from the destination page. Inspect the response and identify which system denied access before changing credentials.

Can I put my REST application key in frontend code?

No. GrabzIt warns that client-side use exposes the application key. Keep REST calls and credentials on a server.

Will a proxy always fix a target-site 403?

No. A proxy is relevant only when the network path requires one; it does not resolve every target authorization or access-control denial.

Can GrabzIt capture any page behind a login?

GrabzIt documents Basic Authentication and session-based login capture, but access still depends on the target’s specific controls.