Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
To capture a webpage from PHP, send its URL and capture options to a hosted screenshot API, then either save the returned image bytes or follow a URL returned in JSON. The quickest provider-specific path is a Composer SDK; a plain HTTP client is more portable. This guide uses ScreenshotOne’s documented PHP SDK for the main example, explains how response formats differ between providers, and shows a browser-free alternative with ScreenshotNeo.
What a PHP screenshot API does
A screenshot API runs a browser renderer on the provider’s infrastructure. Your PHP application submits a target URL (or, with some services, HTML), authentication, and options such as full-page mode or a delay. The service renders the page and returns either binary image data or a response containing a hosted image URL. Your code then stores, proxies, or displays that result.
This avoids installing and operating Chromium, browser drivers, queues, fonts, and sandbox settings in your own PHP deployment. It also means that the provider’s supported PHP version, extensions, authentication scheme, limits, and output format determine the integration details.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsChoose an integration path
| Path | Install and requirements | Authentication | Typical response |
|---|---|---|---|
| ScreenshotOne PHP SDK | Composer package screenshotone/sdk:^1.0; use the PHP version supported by the package. |
Access and secret keys passed to the SDK client. | Binary image bytes from take(); the client can also generate a request URL without downloading. |
| HTML to Image API PHP package | composer require html2img/html2img-php; documentation lists PHP 8.3 or newer and cURL. |
API key kept in the environment and sent in an X-API-Key header. |
Its HTML route returns JSON containing a CDN URL; its website route accepts a URL and capture options. |
| ScreenshotAPI PHP SDK | composer require screenshotapi/sdk; package documentation lists PHP 8.1+. |
API key in the x-api-key header. |
Example code saves the returned image to a file. Confirm the current package behavior before assuming a format. |
| Raw HTTP request | PHP cURL or an HTTP client already used by your application. | Provider-specific query parameter, header, or signed URL. | Whatever the endpoint documents: bytes, JSON, or a URL. |
These requirements are vendor-specific, not universal PHP requirements. Package metadata for ScreenshotAPI identifies version 1.0.1, published June 29, 2026 and updated July 29, 2026; those dates describe that package listing and do not establish that it is still the newest release.
#1 Best Overall
Quick start with ScreenshotOne’s PHP SDK
1. Install the package
composer require screenshotone/sdk:^1.0
Composer places the SDK and its dependencies in vendor/. Commit composer.json and composer.lock, but do not commit API secrets.
2. Provide credentials through the environment
The following variable names are an application convention; the documentation example uses placeholder credentials rather than prescribing these names.
export SCREENSHOTONE_ACCESS_KEY='your-access-key'
export SCREENSHOTONE_SECRET_KEY='your-secret-key'
In production, set secrets through your hosting platform or secret manager. Avoid putting them in a repository, a client-side script, a URL logged by a proxy, or an exception message.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →3. Capture and save an image
<?php
require __DIR__ . '/vendor/autoload.php';
use ScreenshotOneSdkClient;
use ScreenshotOneSdkTakeOptions;
$accessKey = getenv('SCREENSHOTONE_ACCESS_KEY');
$secretKey = getenv('SCREENSHOTONE_SECRET_KEY');
if (!$accessKey || !$secretKey) {
throw new RuntimeException('ScreenshotOne credentials are not configured.');
}
$client = new Client($accessKey, $secretKey);
$options = TakeOptions::url('https://example.com')
->fullPage(true);
$image = $client->take($options);
if (file_put_contents(__DIR__ . '/screenshot.png', $image) === false) {
throw new RuntimeException('Could not write screenshot.png');
}
take() returns image bytes in this documented flow, so file_put_contents() is appropriate. Set the destination outside a public directory when the capture is private, or stream it through a controlled download endpoint.
4. Add timing and location only when needed
Dynamic pages may need a delay before capture. Location-sensitive pages may accept latitude, longitude, and accuracy options. The exact method names depend on the SDK version, so copy the option names from the version’s documentation rather than assuming that an option from another provider exists. A delay is not a substitute for waiting on a specific selector when the SDK supports selector-based readiness.
Rank #2
5. Generate a URL instead of downloading immediately
ScreenshotOne’s client can generate a request URL without executing the request. This is useful when a worker, CDN, or browser should fetch the image later. Treat generated URLs as credentials-bearing artifacts if they contain signing data: do not expose them in logs or public HTML unless the provider documents them as safe for that use.
Using a raw PHP HTTP request
A direct request is preferable when you do not want an SDK dependency or when your provider exposes an HTTP API that your existing client already supports. The endpoint, parameter names, signature rules, and response type are provider-specific. The pattern below shows safe handling of a binary response; replace the URL and authentication fields with the chosen service’s documentation.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
<?php
$apiKey = getenv('SCREENSHOT_API_KEY');
$target = 'https://example.com';
if (!$apiKey) {
throw new RuntimeException('SCREENSHOT_API_KEY is not configured.');
}
$ch = curl_init('https://provider.example/v1/screenshot');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 90,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Accept: image/png',
],
CURLOPT_POSTFIELDS => http_build_query([
'url' => $target,
'full_page' => 'true',
]),
]);
$body = curl_exec($ch);
if ($body === false) {
$error = curl_error($ch);
curl_close($ch);
throw new RuntimeException('HTTP transport failed: ' . $error);
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE) ?: '';
curl_close($ch);
if ($status < 200 || $status >= 300) {
throw new RuntimeException("Screenshot API returned HTTP $status");
}
if (stripos($contentType, 'image/') !== 0) {
throw new RuntimeException('Expected an image response, received ' . $contentType);
}
file_put_contents(__DIR__ . '/screenshot.png', $body);
Do not copy this authentication header or endpoint literally to another vendor. Some services use an access-key query parameter, an x-api-key header, or a signed request. Check the HTTP status and content type before writing bytes; an API error can otherwise be saved as a file named .png.
HTML-to-image responses are different
HTML to Image API documents an HTML route that returns JSON with a CDN URL rather than image bytes. Decode that JSON and fetch or store the URL according to its documented lifetime.
<?php
$apiKey = getenv('HTML2IMG_API_KEY');
$payload = json_encode(['html' => '<h1>Invoice</h1>']);
$ch = curl_init('https://provider.example/html');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . $apiKey,
],
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($response === false || $status < 200 || $status >= 300) {
throw new RuntimeException('HTML-to-image request failed.');
}
$data = json_decode($response, true, 512, JSON_THROW_ON_ERROR);
$url = $data['url'] ?? null;
if (!$url) {
throw new RuntimeException('Provider response did not contain a CDN URL.');
}
echo $url;
The URL key and endpoint shown here are illustrative placeholders. Use the provider’s documented JSON schema. Do not treat a URL response as binary data, and do not assume a binary response from a service whose documentation returns JSON.
ScreenshotAPI’s SDK pattern
ScreenshotAPI’s Packagist documentation shows installation with composer require screenshotapi/sdk, PHP 8.1+, an API key in the x-api-key header, and an example that writes the result to a file. Keep the key in getenv() or equivalent configuration. Because package interfaces can change, pin a tested version in your lock file and consult the package’s current README for the exact class and method names before upgrading.
Recommended Free Tools
Useful capture options
Start with the smallest request that meets the requirement. Common options include:
- Full page: captures content beyond the initial viewport; pages with infinite scrolling may never have a meaningful endpoint.
- Viewport and dimensions: emulate a desktop or mobile layout. Confirm whether dimensions are CSS pixels and whether the service supports device scale.
- Delay or readiness: wait for client-side rendering. A selector-based wait is usually more deterministic than an arbitrary long delay.
- Geolocation: provide latitude, longitude, and accuracy only for pages that actually vary by location.
- Element or selector: capture a component instead of the entire document when the provider supports it.
Option names are not portable. Keep provider-specific request construction behind a small PHP service class so changing vendors does not spread parameter differences through controllers and jobs.
Production reliability checklist
- Use a queue for user-triggered or bulk captures so a slow render does not hold an HTTP request open.
- Set an explicit client timeout that exceeds the provider’s normal render window, and retry only transient transport or server errors.
- Use an idempotency key or deterministic storage name when retries could create duplicate files.
- Validate target URLs and block internal network ranges if users can submit arbitrary URLs; this reduces server-side request forgery risk.
- Record status code, provider request ID, elapsed time, and response type, but never log API keys or signed URLs.
- Limit output size and image dimensions before accepting a capture into long-term storage.
- Test pages requiring authentication separately. A server-side screenshot request does not automatically inherit the end user’s cookies.
Common failures and fixes
Composer cannot install the package
Check the package name, PHP version, enabled extensions, and Composer’s reported constraint. Do not “fix” a version conflict by removing the lock file in production; resolve the constraint deliberately and test the resulting dependency set.
HTTP 401 or 403
The key may be missing, expired, sent in the wrong header, or paired with the wrong account. Compare the request with the provider’s authentication documentation and verify that environment variables are available to the PHP process, not only to your interactive shell.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #4
The saved file is not an image
Inspect the status code and Content-Type. Many APIs return JSON error details for invalid options or quota failures. Decode JSON before writing it to a filename ending in .png or .webp.
The page is blank or incomplete
Increase readiness time only after confirming that the page finishes loading. Prefer a documented selector wait, supply required cookies or headers, and check whether the target blocks automated browsers. Lazy-loaded content may require full-page behavior or scrolling support.
Capture times out
Try a simpler URL, remove unnecessary resources, and raise the client timeout within the provider’s limits. For large jobs, move the request to a worker and provide a pending status to the user instead of holding a web request open.
HTML-to-image code expects the wrong response
Follow the route’s documented contract. An HTML route that returns a CDN URL requires JSON decoding and a second fetch; it cannot be handled like an SDK method that returns image bytes.
Or skip the browser setup
ScreenshotNeo provides a single HTTP endpoint for PNG, JPEG, WebP, or PDF captures. The PHP call below uses its documented API base; see the ScreenshotNeo documentation for all options and authentication details.
<?php
$url = 'https://api.screenshotneo.com/v1/shot';
$query = http_build_query([
'access_key' => getenv('SCREENSHOTNEO_API_KEY'),
'url' => 'https://stripe.com',
]);
$ch = curl_init($url . '?' . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 90,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($body === false || $status < 200 || $status >= 300) {
throw new RuntimeException('ScreenshotNeo request failed.');
}
file_put_contents(__DIR__ . '/shot.webp', $body);
ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing result. It also offers an MCP server for Claude, Cursor, and other MCP clients, with take_screenshot, get_page_info, and capture_pdf tools.
Other available controls include full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper settings and page ranges, custom CSS and JavaScript, pre-capture clicks, hidden selectors, selector/delay/network-idle waits, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous jobs with signed webhooks, up to 100 URLs per bulk call, a usage API, an OpenAPI specification, and familiar parameter names that ease migration. Every feature is included on every plan. Pricing is Free for 1,000 shots per month without a card; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free.
Start with 1,000 free screenshots a month with no card, then choose a paid plan starting at $5 for 3,000 shots if your PHP application needs more.
cURL, Python, and Node.js equivalents
The same ScreenshotNeo request can be tested outside PHP:
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)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
Frequently Asked Questions
Can PHP create screenshots without installing Chrome?
Yes. A hosted screenshot API renders the page remotely, so your PHP application only needs to make an authenticated HTTP request and handle the documented response.
Should I use an SDK or cURL?
Use the SDK when its typed helpers and signing logic fit your provider; use cURL or an existing HTTP client when you need a small dependency footprint or a provider has no maintained PHP SDK.
How do I capture a page that requires a login?
Use a provider option for cookies or authorization headers when available, and protect those values as secrets. The browser rendering session will not automatically include your visitors’ cookies.
Why is a screenshot API response sometimes JSON instead of an image?
Different routes and providers have different contracts. Some return binary image bytes, while HTML-rendering routes may return JSON containing a CDN URL; inspect the status and content type before processing the body.
The Bottom Line
For a fast PHP implementation, install the provider’s Composer SDK, keep credentials in environment configuration, construct a URL capture, and verify whether the result is bytes or JSON before saving it. Use ScreenshotNeo when you want a single endpoint with consent cleanup, transparent billing outcomes, MCP access, and a free 1,000-shot monthly tier.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

