How to Screenshot a Long Webpage in PHP with Symfony Panther
Use Symfony Panther to capture a long webpage in PHP by measuring its document dimensions and resizing the browser window. Learn the limits, setup, and alternatives.
To screenshot a long webpage with Symfony Panther, measure the document’s rendered width and height in JavaScript, resize the WebDriver browser window to those dimensions, then call $client->takeScreenshot(). This is a community-reported workaround, not a documented guarantee that Panther captures the full document. Validate it with your page, browser, and driver.
Panther’s documented screenshot call captures the current page, and its screenshot dimensions are controlled by the browser window. Symfony’s guide demonstrates setting explicit window dimensions, but does not promise that resizing will reliably capture every page’s full height. [Symfony Panther documentation; Panther issue #587]
Requirements and setup
Panther drives a real browser through WebDriver. Install Panther in your Symfony project and ensure a compatible browser and driver are available. Symfony documents Chrome and Firefox clients, as well as driver installation approaches; follow the current instructions for your environment because browser and package versions change. [Symfony installation guide]
composer require --dev symfony/panther
The example below uses Chrome. The destination must be reachable from the machine running the browser. Replace https://example.test/long-page with your page URL.
Capture a long page by resizing the browser
<?php
require __DIR__ . '/vendor/autoload.php';
use Facebook\WebDriver\WebDriverDimension;
use Symfony\Component\Panther\Client;
$url = 'https://example.test/long-page';
$output = __DIR__ . '/long-page.png';
$client = Client::createChromeClient();
try {
$client->request('GET', $url);
// Wait for a page-specific ready condition before measuring.
// Replace this selector with an element that appears only when
// the content you need has rendered.
$client->waitFor('#page-content');
$dimensions = $client->executeScript(
'return {
width: Math.max(document.documentElement.scrollWidth, document.body.scrollWidth),
height: Math.max(document.documentElement.scrollHeight, document.body.scrollHeight)
};'
);
if (!is_array($dimensions) || $dimensions['width'] < 1 || $dimensions['height'] < 1) {
throw new RuntimeException('Could not read positive document dimensions.');
}
$client->manage()->window()->setSize(
new WebDriverDimension((int) $dimensions['width'], (int) $dimensions['height'])
);
$client->takeScreenshot($output);
echo "Saved screenshot to {$output}\n";
} finally {
$client->quit();
}
waitFor() is shown with a page-specific selector: use one that accurately reflects the content and state you need. Panther supports JavaScript execution and waiting for elements, but there is no universal readiness condition for arbitrary sites. [Symfony Panther guide]
Why the dimensions include both document and body
Some pages report scroll dimensions on document.documentElement, while page layout or browser behavior can make document.body relevant. Taking the maximum is a defensive measurement, not a browser compatibility guarantee. If the screenshot clips content, inspect the measured dimensions and the resulting image on the exact browser and driver you deploy.
When to measure
Measure only after the desired page state has rendered. A page can initially have a short document and grow after API data, fonts, images, or client-side components load. If content appears after scrolling, this single measurement may not trigger it. Use a page-specific condition or interaction before measuring, and verify that lazy-loaded sections have actually appeared.
What Panther does and does not guarantee
| Method or fact | What the sources establish |
|---|---|
$client->takeScreenshot($path) |
Panther documents taking a screenshot of the current page. The wrapper delegates to the underlying WebDriver screenshot call; it is not itself a documented full-document API. [Symfony guide; Panther Client source] |
| Resize window to document dimensions | A community issue reports measuring scroll dimensions, resizing, then taking the screenshot. Treat it as a workaround and validate it. [Panther issue #587] |
| Chrome or Firefox | Panther supports browser clients through WebDriver. The cited sources do not establish a reliability comparison for this long-page workaround across browsers or drivers. [Symfony guide] |
| Very tall pages | The research sources do not establish maximum dimensions or behavior for extremely long documents. Test the page and environment; do not assume arbitrary heights will work. |
Options and practical choices
- Browser: The example uses
Client::createChromeClient(). Panther also documents Firefox. Choose the browser installed and supported by your deployment, and validate the workaround there. - Window dimensions: This approach sets the window to the measured document size. Symfony’s guide also shows explicit browser window sizing, but that demonstrates screenshot sizing rather than a guaranteed full-page capture.
- Readiness: Wait for a selector or another condition tied to your page. A fixed delay may be too short on a slow response and unnecessarily long on a fast one.
- Output: Panther’s screenshot method takes a path, such as
long-page.png. Ensure the process can write to the destination directory. - Alternative browser-specific techniques: Panther issue #587 discusses a Chrome DevTools full-page clip approach. That is a separate browser-specific route, not a Panther cross-browser API contract; evaluate its implementation and compatibility for your stack before relying on it.
Common problems and fixes
| Symptom | Likely cause | What to do |
|---|---|---|
| Screenshot contains only the visible viewport | The driver captured the current browser viewport despite resizing, or the resize did not take effect as expected. | Log the measured dimensions, confirm the window size after setting it, and test with your exact browser and driver. This workaround is not guaranteed full-page behavior. |
| Bottom of page is missing | Dimensions were measured before content finished loading, or the page grew after measurement. | Wait for a page-specific readiness condition, trigger required interactions or scrolling, then measure again. |
| Screenshot is unexpectedly short | The document dimensions were read before client-rendered content appeared, or the page uses a nested scrolling container. | Check the actual rendered DOM and identify the element that owns the scrolling content. A document-height resize does not automatically capture content hidden inside a separately scrolling element. |
| Browser or driver fails to start | ChromeDriver or GeckoDriver is missing, incompatible, or not configured for the installed browser. | Install and configure a compatible browser and driver using the current Panther setup instructions. [Symfony installation guide] |
waitFor() times out |
The selector is wrong, absent on this route, or never appears because the page failed to load. | Confirm the selector in the rendered page, check navigation and console/network errors, and choose a condition that represents the state you actually need. |
| Screenshot file is missing | The output path is unwritable or its directory does not exist. | Use an absolute path in a writable directory and check the PHP process’s filesystem permissions. |
| Capture is too large or slow | The document dimensions are very large, increasing browser rendering and image encoding work. | Capture only the needed page or region if that meets the task, and validate limits in your environment. The cited sources specify no maximum safe dimensions. |
Performance, reliability, and cost
A long screenshot requires the browser to render a large surface and encode it as an image. As document height grows, memory, capture time, and output size may grow too; the research sources provide no benchmark or universal limit. For repeatable jobs, use a controlled browser/driver setup, wait for the page state you need, record measured dimensions, and check that the output is complete.
With Panther, you operate the browser and driver environment yourself, so account for their setup and runtime in your application. There is no per-screenshot Panther price established by the research dossier. The resize workaround’s reliability depends on the target page and browser/driver combination and should be validated rather than assumed.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF; its docs are at screenshotneo.com/docs.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.test/long-page -o shot.webp
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. Every feature is on every plan.
Sign up for free: 1,000 screenshots a month, no card required.
FAQ
Does Panther have a documented full-page screenshot method?
The cited Symfony guide documents takeScreenshot() for the current page, but does not define it as a guaranteed full-document capture. Resizing to document dimensions is a reported workaround.
Will the resize workaround work with Firefox?
Panther supports Firefox, but the cited sources do not establish cross-browser reliability for this long-page technique. Validate it with your Firefox and driver versions.
Why can lazy-loaded sections be missing?
They may not exist in the document when dimensions are measured. Trigger the page behavior that loads them and wait for the required content before measuring.
Can I use this in a Symfony end-to-end test?
Yes. Panther is used for end-to-end testing and can take screenshots during a test. Keep the full-page behavior under validation because the resizing technique is a workaround, not a guaranteed Panther API.


