ScreenshotNeo

BlogHTML to image & PDF

How to Use ApiFlash to Generate PDF Files from Web Pages

ApiFlash’s documented endpoint returns webpage screenshots, not PDFs. Capture a page as an image, then choose an image-based PDF or a separate HTML-to-PDF service.

By the ScreenshotNeo team4 October 20269 min read

Direct answer: ApiFlash’s documented /v1/urltoimage endpoint captures a webpage as a JPEG, PNG, or WebP image. The reviewed documentation does not describe a PDF output format or PDF endpoint. To use ApiFlash in a PDF workflow, capture the page as an image and convert that image to PDF, or send the page URL to a separate webpage-to-PDF service. These approaches produce different results: an image-based PDF contains a picture of the page, while an HTML-to-PDF renderer can create a document with selectable text and page layout.

This guide shows the ApiFlash capture step, a runnable Python image-to-PDF conversion, and how to decide whether you need a true HTML-to-PDF renderer instead. ApiFlash’s official API documentation describes GET and POST access, authentication, image response modes, capture controls, and errors.

1. Choose the kind of PDF you need

Approach What the PDF contains Use it when
ApiFlash image capture, then image-to-PDF conversion A screenshot embedded on a PDF page. Text is generally not selectable or searchable. You need a visual snapshot, and a single image per PDF page is acceptable.
A separate webpage-to-PDF or HTML-to-PDF service A rendered PDF document, often paginated; output depends on the renderer and its controls. You need selectable text, print layout, multiple pages, or page-size and margin controls.

ApiLayer Marketplace documents a separate Web page to PDF API, and Adobe documents HTML-to-PDF through PDF Services API. These are examples of separate services, not ApiFlash features or a tested comparison. Before choosing one, check whether it accepts a URL, handles authenticated or dynamic pages, supports the page layout you need, and fits your output-delivery and data-handling requirements.

2. Capture the webpage with ApiFlash

  1. Get an access key from your ApiFlash dashboard. Keep it on a server or in a secret store; do not put it in public browser code.
  2. Call https://api.apiflash.com/v1/urltoimage with the key and a fully qualified target URL, including https://.
  3. Save the returned image bytes. Use format=png for the conversion example below, or choose jpeg or webp where appropriate.
  4. For a full-height screenshot, set full_page=true. The documentation says the height parameter is ignored in this mode.

The following examples capture a full-page PNG of https://example.com. Replace the placeholder key and target URL. These calls create an image file, not a PDF.

cURL

curl --fail --silent --show-error -G 'https://api.apiflash.com/v1/urltoimage' \
  --data-urlencode 'access_key=YOUR_ACCESS_KEY' \
  --data-urlencode 'url=https://example.com' \
  --data-urlencode 'format=png' \
  --data-urlencode 'full_page=true' \
  -o page.png

Python

import requests

endpoint = "https://api.apiflash.com/v1/urltoimage"
params = {
    "access_key": "YOUR_ACCESS_KEY",
    "url": "https://example.com",
    "format": "png",
    "full_page": "true",
}

response = requests.get(endpoint, params=params, timeout=90)
response.raise_for_status()

content_type = response.headers.get("Content-Type", "")
if not content_type.startswith("image/"):
    raise RuntimeError(f"Expected image bytes, received {content_type!r}: {response.text[:500]}")

with open("page.png", "wb") as image_file:
    image_file.write(response.content)

print("Saved page.png")

Node.js

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

const endpoint = new URL("https://api.apiflash.com/v1/urltoimage");
endpoint.search = new URLSearchParams({
  access_key: "YOUR_ACCESS_KEY",
  url: "https://example.com",
  format: "png",
  full_page: "true",
});

const response = await fetch(endpoint, { signal: AbortSignal.timeout(90_000) });
if (!response.ok) {
  throw new Error(`ApiFlash returned HTTP ${response.status}: ${await response.text()}`);
}
const contentType = response.headers.get("content-type") ?? "";
if (!contentType.startsWith("image/")) {
  throw new Error(`Expected image bytes, received ${contentType}`);
}
await writeFile("page.png", Buffer.from(await response.arrayBuffer()));
console.log("Saved page.png");

3. Convert the captured image to a PDF

This Python example uses Pillow to put the screenshot on a single PDF page. Install the dependency with python -m pip install requests Pillow. Run the capture script above first, then run this conversion script:

from PIL import Image

with Image.open("page.png") as source:
    page = source.convert("RGB")
    page.save("page.pdf", "PDF", resolution=150.0)

print("Saved page.pdf")

The result is a PDF wrapper around one raster image. The screenshot dimensions determine the image proportions; this example does not paginate the webpage into standard paper-sized pages, add print headers, or preserve selectable text. Large full-page captures can create large image and PDF files. If those properties matter, use a separate HTML-to-PDF renderer and verify its page-size, margin, pagination, font, and dynamic-content behavior.

4. Configure the ApiFlash capture

ApiFlash parameters are passed in the query string for GET requests or as form data for POST requests. Encode query values, especially target URLs and values containing spaces, ampersands, or other reserved characters. The official reference lists these relevant controls:

Need Parameter or behavior Notes
Choose output image format format Documented formats include JPEG, PNG, and WebP. This selects an image format, not PDF.
Capture full page height full_page=true The documented behavior ignores height in full-page mode.
Set viewport width, height The documented defaults are 1920 by 1080 pixels, subject to documented pixel limits and maximum area. Check the current reference for limits.
Wait for rendering wait_until Documented criteria include dom_loaded, page_loaded, and network_idle; the documented maximum for wait_until_timeout is 30 seconds.
Wait for a page element wait_for Waits for a CSS selector. The reference documents a 15-second failure timeout if it does not appear.
Trigger lazy content or animation scroll_page=true Scrolling can trigger lazy-loaded elements or animations. Check the resulting capture for completeness.
Capture an area crop Uses left,top,width,height coordinates, for example 10,20,800,600.
Reduce or remove overlays no_cookie_banners, no_ads The documentation lists these controls; check plan support and current behavior for the pages you capture.
Get links instead of image bytes response_type=json Returns JSON with links to the screenshot and, when enabled, extracted HTML or text. Fetch the screenshot link separately.
Refresh or reuse a result fresh=true, ttl Identical parameter calls can be cached. Use the documented cache controls according to whether freshness or reuse matters.
Use authenticated pages Cookies and headers ApiFlash documents both. Custom headers apply broadly and may interfere with external font requests; the vendor FAQ suggests self-hosted fonts or cookies for authentication in that situation.

For timing, prefer a meaningful selector or a documented load condition over an arbitrary delay when possible. Pages with continuously active network connections may not reach network idle; try another supported condition and confirm that the important content has rendered. ApiFlash says strict bot protection can still block captures; do not assume the API bypasses bot checks.

5. Response modes and secure key handling

By default, ApiFlash returns image bytes and content headers. With response_type=json, it returns a JSON document with a screenshot link and, when enabled, extracted HTML or text links. In JSON mode, download the linked image before running an image-to-PDF conversion; the JSON response itself is not an image file.

Both GET and POST are documented. GET is convenient, but query strings can be recorded in logs. POST sends parameters as form data, but it does not make a secret safe if the request is made from untrusted client-side code. Keep the access key in a trusted backend. ApiFlash publishes guides for proxying calls through Nginx and Cloudflare Workers. If you build a proxy, restrict which target URLs it accepts and avoid exposing an unrestricted screenshot endpoint to anonymous users.

6. Troubleshooting

Symptom Likely cause What to do
HTTP 400 Invalid parameters, malformed or incomplete target URL, or a URL ApiFlash cannot capture. Use a complete https:// URL, URL-encode values, and check parameter spelling and target accessibility.
HTTP 401 The access key is invalid or revoked. Check the dashboard key, update the server-side secret, and ensure the request sends it in the expected parameter or form field.
HTTP 402 The monthly screenshot quota has been exhausted. Check current quota and plan limits in ApiFlash; defer nonessential captures or adjust the plan.
HTTP 403 The current plan does not support a requested feature. Remove the unsupported parameter or verify the current plan feature list.
HTTP 429 Too many requests. Reduce concurrency, queue work, and retry with backoff. The reviewed documentation states 20 requests per second with a burst of 400; confirm this limit before relying on it.
HTTP 500 The API encountered a capture failure. Retry selectively with backoff, record the target and request parameters, and inspect the returned error. Avoid an unbounded retry loop.
Downloaded file is JSON or an error page The request failed, or response_type=json was used while code treated the response as image bytes. Check HTTP status and content type before saving; in JSON mode, parse the response and fetch its screenshot link.
Screenshot misses content Content rendered late, depends on scrolling, needs authentication, or was blocked by site protections. Use a suitable wait_until condition or wait_for selector; try scroll_page=true; provide the required cookies or headers; inspect bot-protection behavior.
Fonts or external assets disappear Broad custom headers may change requests to third-party resources. Limit custom headers where possible; consider self-hosting fonts or using cookies for authentication as suggested in the vendor FAQ.
PDF is huge or unreadable when printed A full-page raster image has many pixels, and the one-page PDF does not automatically paginate to paper. Choose a suitable viewport and image format, or use a real HTML-to-PDF renderer when paper layout or selectable text matters.
Repeated captures show stale content An identical request may be served from cache. Set the documented freshness controls, such as fresh=true, and review the ttl behavior.

7. Performance, reliability, and cost

  • Image size: Full-page captures can be tall and consume memory and disk space. Use the smallest viewport and image quality that still meet the visual requirement, and consider whether full-page output is needed.
  • Wait time: Network-idle waits can take longer or time out on busy sites. Use the narrowest reliable load condition and wait for a selector when the required content is known.
  • Retries: Retry transient failures and rate limits with bounded exponential backoff. Do not retry invalid keys, unsupported parameters, or exhausted quota without correcting the cause.
  • Caching: Identical parameter calls may return cached captures. Caching can avoid unnecessary recaptures when the page is unchanged; use freshness controls when the document must reflect a recent update.
  • Conversion: Image-to-PDF conversion adds storage and processing proportional to screenshot dimensions. A separate renderer adds another service and its own limits and cost; compare its current terms and behavior for your workload.
  • ApiFlash plan costs: The official homepage at research time listed Free at $0 for 100 screenshots, Lite at $7 for 1,000, Medium at $35 for 10,000, and Large at $180 for 100,000 per month, plus custom enterprise pricing. Prices and quotas can change, so verify the current page before budgeting. These figures cover ApiFlash screenshot plans and do not establish the price of a PDF conversion service.

8. Or skip the browser setup

If you need a screenshot image rather than a paginated, selectable-text PDF, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns an image or PDF output. See the ScreenshotNeo API documentation for parameters and response details.

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, popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. The screenshot endpoint does not make the ApiFlash-to-PDF distinction go away: use a separate conversion or PDF service if you specifically need a paginated, selectable-text document.

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

9. FAQ

Can I save an ApiFlash screenshot with a .pdf extension?

Changing the filename extension does not convert the image bytes into a valid PDF. Convert the image with a PDF library or use a PDF renderer.

Will an image-based PDF have searchable text?

Usually not. It contains raster pixels. Searchable text requires a text-based PDF renderer or a separate OCR process.

Does ApiFlash provide a PDF endpoint?

The reviewed official reference documents a URL-to-image endpoint with JPEG, PNG, and WebP output, and does not document PDF generation. Check the current vendor documentation if that capability is essential.

Can I make one PDF page per screen-sized section?

The conversion example makes one PDF page containing the whole screenshot. Splitting a tall capture into paper-sized pages requires an additional image-processing step; a webpage-to-PDF renderer is generally a better fit when pagination matters.