Take a Full-Page Screenshot in PHP with Panther
Panther’s takeScreenshot() captures the browser viewport. Learn a reported full-height workaround, its limits, and the Chrome DevTools Protocol option.
Symfony Panther’s takeScreenshot() method takes a WebDriver screenshot, but it is not documented as a guaranteed full-page capture API. To try capturing the whole document with Panther, measure its scroll dimensions, resize the browser window, then call takeScreenshot(). This is a community-reported workaround with limitations. If you need a documented way to capture beyond the viewport in Chrome, use Chrome DevTools Protocol (CDP) and set captureBeyondViewport to true.
Panther drives real browsers through WebDriver for browser testing and crawling. Its README documents screenshot capture, browser clients, and waiting for page elements. The examples below distinguish Panther’s ordinary screenshot call, the window-resize workaround, and the Chrome-only protocol route. See the Symfony Panther project README for current setup instructions.
1. Install Panther and capture a browser viewport
Install Panther with Composer, then make sure the browser and matching driver required by your chosen client are available. Panther documents Chrome and Firefox clients; its browser-driver setup can change, so follow the project’s current instructions for your environment.
composer require symfony/panther
This runnable PHP example requests a page and saves a screenshot of the current browser viewport:
<?php
require __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Panther\Client;
$client = Client::createChromeClient();
$client->request('GET', 'https://example.com');
$client->takeScreenshot(__DIR__ . '/viewport.png');
$client->quit();
Use Client::createFirefoxClient() when you want to run the ordinary WebDriver screenshot flow with Firefox. The documented call does not by itself promise that the image includes content beyond the current viewport.
2. Try the document-size and window-resize workaround
A Panther support issue describes measuring document.documentElement.scrollWidth and scrollHeight, resizing the controlled window to those dimensions, then taking an ordinary screenshot. The issue’s author explicitly questions whether the technique will work in every case, so treat it as a workaround to evaluate with your browser and target pages—not as a Panther full-page API.
<?php
require __DIR__ . '/vendor/autoload.php';
use Facebook\WebDriver\WebDriverDimension;
use Symfony\Component\Panther\Client;
$client = Client::createChromeClient();
$client->request('GET', 'https://example.com');
$width = (int) $client->executeScript(
'return document.documentElement.scrollWidth'
);
$height = (int) $client->executeScript(
'return document.documentElement.scrollHeight'
);
if ($width < 1 || $height < 1) {
throw new RuntimeException('The page has no measurable document dimensions.');
}
$client->manage()->window()->setSize(new WebDriverDimension($width, $height));
$client->takeScreenshot(__DIR__ . '/full-page-attempt.png');
$client->quit();
The integer casts make the dimensions explicit for WebDriver. The basic sample assumes the page has finished rendering enough content to measure. If the site renders asynchronously, wait for a known element before measuring; Panther’s documentation describes waiting for rendered elements. Dynamic content and lazy-loaded sections may require page-specific handling, and the cited workaround does not establish a universal strategy for loading them.
What can go wrong with resizing?
- The layout changes: resizing can trigger responsive breakpoints, so the page may reflow and differ from the layout at the original viewport.
- Content is still loading: dimensions measured too early can omit content that appears later. Wait for a page-specific rendered element before measuring.
- The result is incomplete or unusable: the community report does not establish that arbitrary page sizes work. Check the output on your actual pages and browser.
- Sticky or fixed elements behave differently: the approach changes the window size; inspect whether those elements appear as intended in the resulting image.
The sources do not establish a universal maximum screenshot size for Panther or WebDriver. Avoid assuming that very tall pages will work just because their dimensions can be read; validate output size, browser behavior, and runtime for your use case.
3. Use Chrome DevTools Protocol to capture beyond the viewport
Chrome DevTools Protocol defines Page.captureScreenshot. Its captureBeyondViewport option defaults to false; set it to true to request capture beyond the viewport. The method also supports an optional clip region and PNG, JPEG, or WebP output. This is Chrome protocol functionality, not a built-in cross-browser Panther convenience method.
Panther’s standard takeScreenshot() wrapper is not evidence that it exposes this CDP option directly. To use CDP, connect to and send commands to the Chrome DevTools Protocol endpoint for the browser session. The exact connection and command transport depend on how Chrome is launched and how your application manages its debugging endpoint; the Panther sources cited here do not provide a complete Panther-to-CDP PHP client example. Keep the boundary clear: this method is Chrome-specific and requires CDP integration in addition to the ordinary WebDriver call.
At the protocol level, the request is conceptually:
{
"method": "Page.captureScreenshot",
"params": {
"format": "png",
"captureBeyondViewport": true
}
}
If you provide clip, it restricts the capture to the specified region. Choose PNG, JPEG, or WebP according to your output requirements. Consult the Chrome DevTools Protocol Page.captureScreenshot reference for the protocol schema and current parameters.
4. Choose the capture route
| Route | Browser scope | What it does | Key caveat |
|---|---|---|---|
Panther takeScreenshot() |
Panther WebDriver client | Saves a screenshot through WebDriver. | Not documented as a guaranteed full-page capture. |
| Measure and resize | Panther client, subject to browser behavior | Measures document dimensions, resizes the window, and uses takeScreenshot(). |
Community workaround; can alter responsive layout and is not guaranteed to work in every case. |
CDP with captureBeyondViewport |
Chrome | Requests a screenshot extending beyond the viewport; supports an optional clip and output format. | Requires Chrome DevTools Protocol integration; not a cross-browser Panther convenience method. |
For a Panther-based test suite that already uses WebDriver, start with the resize workaround if its caveats are acceptable and validate the output against representative pages. If reliable beyond-viewport behavior in Chrome is a requirement, integrate the documented CDP method and test it against your Chrome setup. If you require Firefox or another browser, the CDP route described here does not apply.
5. Wait for the right page state
A screenshot only reflects what the browser has rendered when capture occurs. A fixed sleep may be too short on a slow page and waste time on a fast one. Prefer waiting for a meaningful page-specific element when the page provides one, using Panther’s documented wait support. For the resize workaround, wait before reading dimensions; for either approach, make sure the content you care about is present.
- Navigate to the page.
- Wait for a selector that indicates the relevant content has rendered.
- If needed, allow page-specific asynchronous content to settle.
- For the resize route, measure dimensions only after that state is reached.
- Capture, then inspect the image for missing sections, layout shifts, and unwanted overlays.
There is no universal lazy-loading recipe established by the Panther issue or protocol reference here. Pages may load images or sections only after scrolling or other interaction; handle that behavior according to the target site rather than assuming a full-height dimension measurement will load every asset.
6. Run Panther with remote browsers when needed
The Panther project documentation describes remote browser services, including BrowserStack and Sauce Labs. Remote execution can help teams run browser tests in managed environments, but browser and driver configuration still matters. Follow Panther’s current setup guidance and the remote provider’s instructions; verify the screenshot behavior on the browser version and viewport used in your job.
7. Troubleshoot common problems
| Symptom | Likely cause | Fix |
|---|---|---|
| PHP reports that the Panther class or package is missing. | Panther dependencies are not installed or Composer’s autoloader is not loaded. | Run the Composer installation command in the project and require vendor/autoload.php. |
| Chrome or Firefox fails to start. | The browser or a compatible driver is unavailable or misconfigured. | Use Panther’s current browser-driver setup instructions and confirm the browser is installed in the execution environment. |
| The screenshot contains only the visible viewport. | The ordinary WebDriver screenshot call captured the viewport. | Try the documented-as-a-workaround resize approach, or use CDP’s captureBeyondViewport: true with Chrome. |
| The resized screenshot has a different layout. | The larger window crossed responsive breakpoints or changed page behavior. | Use a capture method that does not rely on changing the viewport, or accept and account for the resized layout in your test. |
| The image is missing content near the bottom. | Content had not rendered when dimensions were read, or the page loads content dynamically. | Wait for the relevant element or page state before measuring and capture; handle site-specific lazy loading explicitly. |
| The CDP command is rejected or unavailable. | The request is not being sent through a Chrome DevTools Protocol connection, or the session/command setup is wrong. | Confirm that the browser is Chrome, establish the correct CDP connection for that session, and check the protocol method and parameter names. |
| The saved file is missing or has unexpected contents. | The output path may be wrong, or the page capture failed before saving. | Use an explicit writable path, check the returned result and filesystem permissions, and verify the browser session remains active. |
8. Performance, reliability, and cost considerations
- Performance: waiting for page content, changing the window size, and capturing a large page all add work. Capture only when the needed page state is ready, and avoid unnecessary fixed delays.
- Reliability: the resize method is explicitly an uncertain community workaround. CDP documents the beyond-viewport option, but its use is Chrome-specific and still depends on correct protocol integration and page state.
- Output size: a full-height image can be substantially larger than a viewport image. The cited sources provide no general numerical size limit, so measure runtime and output for your own pages.
- Cost: Panther is a PHP library; the dossier does not establish pricing for browser hosting or remote browser services. If you use a remote provider, check its current pricing separately.
Or skip the browser setup
For a hosted screenshot call, ScreenshotNeo is a website screenshot API and MCP server. Its API accepts one GET request with a URL and can return PNG, JPEG, WebP, or PDF. For a full-page capture, use the documented full-page option and see the ScreenshotNeo API documentation for request parameters:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
ScreenshotNeo removes cookie banners, 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; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
FAQ
Does Panther have a dedicated full-page screenshot method?
The cited Panther README documents takeScreenshot(), but not a guarantee that it captures the full scrollable page. The resize workaround is community-reported.
Can Panther capture beyond the viewport in Firefox with the Chrome protocol option?
No. The cited Page.captureScreenshot option belongs to Chrome DevTools Protocol. The dossier does not establish an equivalent Firefox route.
Should I use the resize workaround in a browser test?
Use it only when its layout changes and uncertain behavior are acceptable for your test, and verify the result on the pages and browser you run.
Does reading the page height load lazy images?
Not necessarily. A document height measurement is not a universal lazy-loading strategy; handle the page’s loading behavior explicitly.
Sources
- Symfony Panther README and project documentation: installation, browser clients, waits, screenshots, and remote browser setup.
- Panther issue discussion on full-page screenshots: reported dimension measurement and window resizing workaround, with uncertainty about reliability.
- Chrome DevTools Protocol: Page.captureScreenshot: beyond-viewport option, clipping, and output formats.


