Oh Dear is the all-in-one monitoring tool for your entire website. We monitor uptime, SSL certificates, broken links, scheduled tasks and more. You'll get a notifications for us when something's wrong. All that paired with a developer friendly API and kick-ass documentation. O, and you'll also be able to create a public status page under a minute. Start monitoring using our free trial now.

Another new Spatie package drops: spatie/laravel-screenshot

Original – by Freek Van der Herten – 4 minute read

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.

Share Post LinkedIn

I write about Laravel, PHP, AI and building better software.

Every two weeks, I share practical tips, tutorials, and behind-the-scenes insights from maintaining 300+ open source packages. Join thousands of developers who read along.

No spam. Unsubscribe anytime. You can also follow me on X.

Found something interesting to share?

The community section is a place where developers share links to articles, tutorials and videos. Submit a link and help fellow developers discover great content. As a thank you, you'll receive a coupon for a discount on Spatie products.