Another new Spatie package drops: spatie/laravel-screenshot
We just released laravel-screenshot, a new package to take screenshots of web pages in Laravel apps.
It uses a driver-based architecture, so you can choose between Browsershot (which requires you to install Chromium) and Cloudflare Browser Rendering (which can be used on environments like Laravel Cloud).
Let me walk you through the package.
Taking screenshots
The most common use case is screenshotting a URL:
use Spatie\LaravelScreenshot\Facades\Screenshot; Screenshot::url('https://example.com')->save('screenshot.png');
You can also take a screenshot from a string of HTML. This is handy when you want to render something yourself, like a chart generated by a JavaScript library:
Screenshot::html('<h1>Hello world!</h1>')->save('hello.png');
There are plenty of options to customize the output. You can set the viewport size, image format, and quality:
Screenshot::url('https://example.com') ->width(1920)->height(1080) ->quality(80) ->save('screenshot.jpg');
The image format is automatically determined from the file extension. Pass .jpg for JPEG, .webp for WebP, or .png for PNG.
If you want to capture the entire scrollable page instead of just the viewport, call fullPage():
Screenshot::url('https://example.com') ->fullPage() ->save('full-page.png');
You can also screenshot a specific element on the page using a CSS selector:
Screenshot::url('https://example.com') ->selector('.hero-section') ->save('hero.png');
Need a specific region? Use clip() with x, y coordinates and dimensions:
Screenshot::url('https://example.com') ->clip(0, 0, 800, 600) ->save('clipped.png');
For transparent backgrounds, useful when screenshotting individual elements like logos, there is omitBackground():
Screenshot::url('https://example.com') ->selector('.logo') ->omitBackground() ->save('logo.png');
By default, screenshots wait for the network to be idle before capturing. You can customize this behavior to wait for a CSS selector to appear, or wait for a specific duration:
Screenshot::url('https://example.com') ->waitForSelector('.content-loaded') ->save('screenshot.png'); Screenshot::url('https://example.com') ->waitForTimeout(3000) ->save('screenshot.png');
The Cloudflare driver
Just like our laravel-pdf package, laravel-screenshot ships with a Cloudflare driver. This uses Cloudflare's Browser Rendering API to take screenshots, which means you don't need Node.js or a Chrome binary on your server. Perfect for Laravel Cloud or any serverless environment.
To use it, set the driver in your .env file and provide your Cloudflare credentials:
LARAVEL_SCREENSHOT_DRIVER=cloudflare CLOUDFLARE_API_TOKEN=your-api-token CLOUDFLARE_ACCOUNT_ID=your-account-id
That's it. All your existing Screenshot::url() calls will now use Cloudflare instead of Browsershot. No code changes needed.
You can also switch drivers per screenshot if you want to use Cloudflare for some screenshots and Browsershot for others:
Screenshot::url('https://example.com') ->driver('cloudflare') ->save('screenshot.png');
Extending with macros
The ScreenshotBuilder class uses Laravel's Macroable trait, so you can define reusable screenshot configurations. Register macros in a service provider:
use Spatie\LaravelScreenshot\ScreenshotBuilder; ScreenshotBuilder::macro('mobile', function () { return $this ->size(375, 812) ->deviceScaleFactor(3); }); ScreenshotBuilder::macro('desktop', function () { return $this ->size(1920, 1080) ->deviceScaleFactor(2); });
Then use them anywhere in your app:
Screenshot::url('https://example.com') ->mobile() ->save('mobile.png');
Testing
The package has first-class testing support. Call Screenshot::fake() to swap the real screenshot builder for a fake one that captures everything without actually taking screenshots:
use Spatie\LaravelScreenshot\Facades\Screenshot; it('takes a screenshot', function () { Screenshot::fake(); $this->get(route('screenshot'))->assertOk(); Screenshot::assertSaved(function ($screenshot) { return $screenshot->url === 'https://example.com'; }); });
In closing
I had a lot of fun creating this one. Thruth be told, my AI could already get a good head start by looking how I built and polished the spatie/laravel-pdf package, which follows a similar structure. You can find the code of the package on GitHub. We also have extensive docs on our website.
This is one of the many packages we've created at Spatie. If you want to support our open source work, consider picking up one of our paid products.