ScreenshotNeo

BlogHow-to

How to capture a webpage as a JPEG with a screenshot API

Capture a webpage as a JPEG with a screenshot API. Learn how to request JPEG output, save the image, capture full pages, tune quality, and fix common issues.

By the ScreenshotNeo team4 October 20268 min read

To capture a webpage as a JPEG, send its URL to a screenshot API, request JPEG output, and save the response bytes with a .jpg or .jpeg extension. Add the provider’s full-page option when you need content below the visible browser area. JPEG quality, authentication, and rendering controls vary by provider, so use that API’s documented parameter names.

How do I capture a webpage as a JPEG with an API?

A screenshot API opens the requested URL in a browser, renders the page, and returns image bytes. It does not photograph a physical screen. The basic workflow is:

  1. Choose the URL and the screenshot API.
  2. Authenticate with a private API key or token.
  3. Request JPEG using the provider’s documented option.
  4. Choose viewport or full-page capture.
  5. Save the binary response to a file and check that it is a valid JPEG.

Two documented patterns are a GET query string and a POST JSON request. ScreenshotOne uses format=jpeg (with jpg as an alias); Browserless uses options.type="jpeg". Their option names and rendering behavior are provider-specific. See the ScreenshotOne options documentation and Browserless Screenshot API documentation.

Choose an API request style

ScreenshotOne: GET request

URL-encode the target page URL and request JPEG with format=jpeg. The following URL is illustrative; replace the placeholder with your key and encode the target URL in production:

https://api.screenshotone.com/take?url=https%3A%2F%2Fexample.com&format=jpeg&access_key=YOUR_ACCESS_KEY

To capture the full page, add full_page=true:

https://api.screenshotone.com/take?url=https%3A%2F%2Fexample.com&format=jpeg&full_page=true&access_key=YOUR_ACCESS_KEY

ScreenshotOne documents jpg as an alias and says its default format is also JPG. Explicitly requesting JPEG makes the intent clear and avoids relying on defaults.

Browserless: POST request

Send JSON to the screenshot endpoint and write the response body as a file. The API token is included in the endpoint query string, so keep it private:

curl -X POST \
  'https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com/","options":{"type":"jpeg","fullPage":true}}' \
  --output screenshot.jpg

Browserless documents options.type values that determine whether the response is PNG or JPEG, and options.fullPage=true for full-page capture. Check the current provider documentation for additional options and account constraints.

Save the JPEG using cURL, Python, or Node.js

Use binary-safe output. Do not print image bytes as text or treat the response as JSON. These examples show the Browserless POST pattern from its documentation.

cURL

curl --fail-with-body -X POST \
  'https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com/","options":{"type":"jpeg","fullPage":true}}' \
  --output screenshot.jpg

--output writes the response body to a file. --fail-with-body makes HTTP errors visible while preserving an error response body where available; if your cURL version does not support that option, omit it and inspect the HTTP status separately.

Python

import os
import requests

url = "https://production-sfo.browserless.io/screenshot"
token = os.environ["BROWSERLESS_TOKEN"]
payload = {
    "url": "https://example.com/",
    "options": {"type": "jpeg", "fullPage": True},
}

response = requests.post(
    url,
    params={"token": token},
    json=payload,
    timeout=90,
)
response.raise_for_status()

content_type = response.headers.get("Content-Type", "")
if "image/jpeg" not in content_type:
    raise ValueError(f"Expected image/jpeg, received {content_type!r}")

with open("screenshot.jpg", "wb") as image_file:
    image_file.write(response.content)

Install the dependency with python -m pip install requests. Keep the token in an environment variable or a server-side secret store, not in a public repository or browser code.

Node.js

const token = process.env.BROWSERLESS_TOKEN;
if (!token) throw new Error('Set BROWSERLESS_TOKEN first');

const endpoint = new URL('https://production-sfo.browserless.io/screenshot');
endpoint.searchParams.set('token', token);

const response = await fetch(endpoint, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    url: 'https://example.com/',
    options: { type: 'jpeg', fullPage: true },
  }),
  signal: AbortSignal.timeout(90_000),
});

if (!response.ok) {
  throw new Error(`Screenshot API returned HTTP ${response.status}: ${await response.text()}`);
}

const contentType = response.headers.get('content-type') || '';
if (!contentType.includes('image/jpeg')) {
  throw new Error(`Expected image/jpeg, received ${contentType}`);
}

const fs = await import('node:fs/promises');
await fs.writeFile('screenshot.jpg', Buffer.from(await response.arrayBuffer()));

This uses the built-in fetch available in current Node.js versions. In production, choose a timeout consistent with your provider’s documented limits and your own request budget.

How do I get a full-page website screenshot?

Viewport capture includes only the visible browser area. Full-page capture attempts to include content below the fold. Set the provider’s full-page option: full_page=true for ScreenshotOne or options.fullPage=true for Browserless.

Long pages can contain lazy-loaded images or sections that load only after scrolling. Browserless documents scrollPage: true to scroll before capture, which can help trigger lazy content; it can be combined with full-page mode. ScreenshotOne documents full-page scrolling as enabled by default with full_page=true, unless overridden. See its full-page screenshot guide.

Full-page output may be very tall and large. If the capture is incomplete, allow more rendering time or enable scrolling where supported. These changes increase request time, so add them only when the page needs them. Complex layouts can render differently under different full-page methods; inspect the resulting file.

How do I set screenshot quality?

JPEG is a lossy format: lowering quality can reduce file size while introducing visible compression artifacts. Quality controls differ by service. ScreenshotOne documents image_quality from 0 to 100, with a default of 80. The documentation does not prescribe one best value for every page. Choose based on the use case and inspect the output at its intended display size.

Use case Practical approach
Small preview or thumbnail Try a lower quality, then check text edges and gradients at the displayed size.
Visual review or sharing Start near the provider default and inspect fine text, charts, and image detail.
Archival or pixel-sensitive review Use a high quality setting if supported; consider whether JPEG is appropriate for the required fidelity.

Do not assume that the same quality number produces identical results across APIs. Confirm the response format from the response headers or by opening the saved file, rather than trusting only its filename.

Options to decide before capture

Decision What to specify Why it matters
Output format JPEG using that API’s format option Names and defaults vary by provider.
Capture area Viewport or full page Viewport omits below-the-fold content.
Rendering wait Delay, selector wait, or scrolling if supported Dynamic and lazy content may not be ready immediately.
Quality Provider-specific quality value Balances file size against compression artifacts.
Authentication Key or token sent server-side Credentials in public client code can be copied and abused.
Response handling Binary file write and status/content-type checks Error pages must not be saved as if they were JPEGs.

Other useful controls may include viewport dimensions, device emulation, wait conditions, and page scrolling, but their names and availability are provider-specific. Consult the API documentation before copying an option between services.

Troubleshooting

Symptom Likely cause Fix
Saved file will not open as an image An HTTP error or JSON/text error body was written with a JPG extension. Check the status code and content type before writing the file. Print the error body for diagnosis.
Image is PNG despite a JPG filename The requested format option was omitted, misspelled, or not supported by the endpoint. Use the documented JPEG setting: format=jpeg on ScreenshotOne or options.type="jpeg" on Browserless. Verify the returned content type.
Only the top of the page appears The request captured the viewport only. Enable full-page capture with the provider’s exact option.
Images or sections are missing Content may be lazy-loaded or still rendering at capture time. Allow more time; where supported, scroll the page before capture to trigger lazy loading.
Text or edges look blocky JPEG compression quality is too low for the content. Increase quality if the API supports it, and compare output file size and visual detail.
Request times out The site may be slow, the page may wait on long-running resources, or full-page rendering may take longer. Set a suitable client timeout, use only the wait behavior the page requires, and check provider limits and errors.
Authentication fails Missing, invalid, expired, or incorrectly placed credential. Check the key or token configuration and endpoint format. Keep credentials out of public code and logs.

Performance, reliability, and cost

Every screenshot request depends on the destination site’s load behavior and the provider’s rendering process. Full-page capture, extra waiting, scrolling, and large viewport dimensions can increase latency and response size. Capture only the necessary area, avoid adding arbitrary delays, and set client timeouts to match the provider’s documented behavior.

For reliable integrations, handle non-success status codes, validate that the response is actually JPEG, and retry only transient failures with a bounded policy. Avoid blindly retrying authentication errors or invalid URLs. If you capture many pages, check the provider’s current quotas, concurrency limits, retention policies, and pricing before choosing a plan; those terms were not established by the sources cited here.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. A single GET request can return a JPEG, PNG, WebP, or PDF; see the ScreenshotNeo API documentation for the JPEG format option and other parameters.

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

In the request, add the documented JPEG output parameter to return a JPEG. ScreenshotNeo accepts parameter names used by other screenshot APIs to make switching easier. Its clean-capture steps accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, with response headers identifying the page verdict and billing status. ScreenshotNeo also has an MCP server with take_screenshot, get_page_info, and capture_pdf tools for AI agents. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.

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

Frequently asked questions

Should I use .jpg or .jpeg?

Either extension is commonly used for JPEG files. Use the extension your downstream system expects, and confirm the response itself is JPEG.

Can an API capture a page that requires login?

Only if the provider supports the required authentication state, such as cookies or headers, and you are authorized to access the page. Check that provider’s documentation and avoid exposing session credentials.

Does JPEG preserve transparency?

JPEG does not preserve transparent pixels. If transparency matters, choose a format that supports it and that the API offers.

Is full-page capture always a single continuous image?

That depends on the provider’s implementation and the page. Full-page options aim to include content below the fold; inspect the result for sticky elements, lazy sections, and layout changes.

Sources