ScreenshotNeo

BlogHow-to

How to Debug 403 and 429 Errors from the Html2Pdf.app API

Learn what Html2Pdf.app documents about 403 errors, what remains unknown about 429, and how to check requests without misreading an error as a PDF.

By the ScreenshotNeo team4 October 20268 min read

Start by checking the HTTP status before treating the response as a PDF. Html2Pdf.app documents 403 as an account limit included in the current plan: review the plan limits and the notification email for the account. Its reviewed status documentation does not define 429, its trigger, or a retry policy. Do not assume a 429 means the same thing as a 403 or apply a retry schedule the provider has not documented.

The documented endpoint is POST https://api.html2pdf.app/v1/generate. Send a JSON request and authenticate with the X-API-Key header. Keep the key in a trusted backend, server-side script, or job. The provider cautions against exposing it in browser JavaScript, public repositories, or client-side templates. Html2Pdf.app API documentation.

1. Capture the status before handling the response

A common integration mistake is to save every response body with a .pdf extension or return it with Content-Type: application/pdf. A non-2xx response is an error response; inspect its status and preserve its details before handing bytes to a PDF consumer. A body that contains an error message is not a PDF just because the request was intended to generate one.

For diagnosis, log the HTTP status, timestamp, request parameters that are safe to record, and any response details supplied by the server. Never log the API key. Keep a small, redacted request example so you can reproduce the same call from a terminal.

2. Reproduce the call with cURL

Set the key as an environment variable in the shell where you run the command. The following sends a JSON body and writes the response body to a file while also printing the HTTP status. Replace the example URL and request body with the values your integration uses; use the exact request fields required by your Html2Pdf.app setup.

export HTML2PDF_API_KEY='your-api-key'

curl --silent --show-error \
  --request POST 'https://api.html2pdf.app/v1/generate' \
  --header "X-API-Key: $HTML2PDF_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{"url":"https://example.com"}' \
  --output response.bin \
  --write-out '\nHTTP %{http_code}\n'

This command is for checking the request path and HTTP status. If the endpoint expects additional conversion options for your use case, add the documented JSON fields from the provider’s API reference. Do not treat the example body as a complete schema.

The official cURL guide shows how to handle non-2xx responses and keep the key in an environment variable. For output problems such as a blank page or missing styling, it recommends checking that the source URL and its CSS, fonts, and images are publicly reachable. Those checks can help diagnose input or rendering issues; they are not documented explanations for a 429.

3. Interpret the status codes separately

Status What the provider documents What to do
400 The source URL may be inaccessible or a request parameter invalid. Check the JSON, parameter values, and whether the source URL can be reached by the conversion service.
401 The API key is missing or invalid. Check that the request includes X-API-Key and that the key is correct and active. Keep it private.
403 The account has reached a limit included in its current plan. Review plan limits and the notification email sent to the account. Resolve the limit issue before retrying.
429 The reviewed official status table does not define this response. Save the status and available response details, then ask Html2Pdf.app support for the account-specific cause and recovery advice.
500 An unhandled server error. The provider suggests retrying after a short delay, increasing delays between repeated attempts, and contacting support if it persists.

Html2Pdf.app’s documentation says: “Do not automatically retry 400, 401, or 403 responses without first correcting the request, credentials, or account limit.” Apply that instruction to those documented statuses. The same documentation does not establish a retry policy for 429.

4. Debug a 403 response

  1. Confirm the status is actually 403. Record the response code before parsing or saving the body as a PDF.
  2. Check the account plan limits. The provider attributes 403 to reaching a limit included in the current plan.
  3. Check the account notification email. The documentation specifically points to this as a place to review account-limit information.
  4. Resolve the account issue, then retry. Do not repeatedly send the unchanged request; the provider says not to automatically retry 403 before correcting the account limit.
  5. Keep the error path distinct from PDF delivery. Return an appropriate application error to your caller rather than labeling the error body as a PDF.

A 403 in this API is not documented as a malformed-key error. The provider documents a missing or invalid key as 401, so check credentials when you receive 401 rather than using the 403 explanation for every authorization-looking failure.

5. Debug a 429 response without guessing

The official status table reviewed for this guide does not say what triggers a 429, whether it is tied to request frequency, what time window applies, whether response headers expose a limit, or how long to wait before trying again. A targeted search for provider-specific 429 or rate-limit guidance did not resolve these questions. Treat the cause and recovery behavior as unknown until the provider confirms them.

  1. Preserve the original response. Record the status, time, endpoint, and any non-secret response details or headers that your HTTP client exposes.
  2. Do not relabel it as a plan-limit 403. The documented 403 explanation does not establish the meaning of 429.
  3. Avoid an invented retry schedule. The provider’s delayed retry guidance is for 500 errors; the reviewed docs do not extend it to 429.
  4. Ask support for account-specific guidance. Include the timestamps, request pattern, status, and redacted response details. Ask what triggered the response and what recovery behavior the provider recommends.
  5. Keep your integration observable. Distinguish 429 from 403 and other failures in logs and metrics so you can act on the provider’s answer without confusing status classes.

6. Python example with safe response handling

This runnable example uses requests, reads the key from the environment, sends JSON, and checks the status before writing a PDF. It intentionally does not retry 403 or 429. Add only request fields supported by the provider’s API documentation for your conversion.

import os
import requests

api_key = os.environ["HTML2PDF_API_KEY"]
endpoint = "https://api.html2pdf.app/v1/generate"
payload = {"url": "https://example.com"}

response = requests.post(
    endpoint,
    headers={"X-API-Key": api_key},
    json=payload,
    timeout=90,
)

if not response.ok:
    print(f"Html2Pdf.app returned HTTP {response.status_code}")
    print(response.text[:2000])  # Inspect only; redact before sharing.
    response.raise_for_status()

with open("output.pdf", "wb") as pdf_file:
    pdf_file.write(response.content)

The timeout shown is a client-side example, not a provider-documented service limit. Choose a timeout appropriate to your application and conversion needs. Ensure error details do not expose secrets or sensitive page content in centralized logs.

7. Node.js example with status checks

This example uses the built-in fetch available in current Node.js releases. It keeps the key in an environment variable and only writes the response body when the HTTP status is successful.

import { writeFile } from "node:fs/promises";

const apiKey = process.env.HTML2PDF_API_KEY;
if (!apiKey) throw new Error("Set HTML2PDF_API_KEY first");

const response = await fetch("https://api.html2pdf.app/v1/generate", {
  method: "POST",
  headers: {
    "X-API-Key": apiKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ url: "https://example.com" }),
});

if (!response.ok) {
  const details = await response.text();
  console.error(`Html2Pdf.app returned HTTP ${response.status}`);
  console.error(details.slice(0, 2000));
  throw new Error("PDF conversion failed");
}

const bytes = new Uint8Array(await response.arrayBuffer());
await writeFile("output.pdf", bytes);

8. Reliability, performance, and cost considerations

Reliability: classify failures by status and keep enough redacted context to reproduce them. Do not retry a deterministic 400, 401, or 403 unchanged. For 429, ask the provider for the specific recovery policy before choosing automatic retries. For 500, follow the provider’s documented suggestion to retry after a short delay with increasing delays between repeated attempts, and contact support if it continues.

Performance: an HTTP 403 or 429 is a failed conversion response, not evidence that changing PDF rendering settings will fix the problem. Check authentication and account status for 403; preserve details and obtain provider guidance for 429. For successful but blank or unstyled output, verify that the source URL and its dependent CSS, fonts, and images are publicly reachable.

Cost: the researched documentation does not specify the billing treatment of 403 or 429 responses. Do not infer whether either response consumes quota or incurs a charge; consult the plan terms or support for account-specific billing details.

9. Troubleshooting checklist

  • The code says PDF, but the file will not open: inspect the HTTP status first. Do not save a non-2xx error body as a PDF.
  • You get 401: verify the X-API-Key header and key. Keep the key server-side and out of browser code and repositories.
  • You get 403: review the plan limits and account notification email. Correct the account-limit issue before retrying.
  • You get 429: the reviewed provider material does not define its cause or retry interval. Preserve response details and ask support instead of borrowing the 403 or 500 explanation.
  • You get 400: check the request parameters and source URL accessibility.
  • You get 500: follow the provider’s short-delay, increasing-delay retry recommendation and contact support if it persists.
  • The PDF is blank or missing styles: check public reachability of the source page and its CSS, fonts, and images. This is an output diagnosis and is not documented as a 429 fix.

10. Or skip the browser setup

If the task is simply to capture a clean website screenshot or PDF, ScreenshotNeo provides a screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF. The API also reports whether a request was billed and its page verdict in response headers.

See the ScreenshotNeo API documentation. Example cURL request:

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

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, and paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

FAQ

Does a 403 mean my API key is wrong?

Not according to the provider’s status table: it maps 403 to an account limit included in the current plan. The provider maps a missing or invalid key to 401.

Can I use a browser-side request to test my key?

The provider says to keep the API key private and use it from a backend, server-side script, or trusted job. Do not put it in browser JavaScript or a client-side template.

Does a 429 mean I should wait one minute?

The reviewed documentation does not define a retry interval or window for 429. Ask Html2Pdf.app support for its recommendation.

Does the provider charge for these errors?

The researched status documentation does not answer billing treatment for 403 or 429. Check the plan terms or ask support.

Sources