keepcalculator

06 Numbers and Powers

Laravel Screenshot Multiple URLs Guide

Card No. 06·52187 · Updated · Standard formula, shown below

This guide shows you how to capture screenshots of multiple URLs directly from your Laravel application. You’ll learn to set up a screenshot service, loop through a list of URLs, save the images, and handle common issues. By the end, you’ll have a reusable command or controller that can generate screenshots for any set of web pages, perfect for generating previews, monitoring visual changes, or creating site galleries.

What You’ll Need

  • A Laravel project (version 8 or later recommended)
  • Composer installed
  • Node.js and npm installed (for Puppeteer, one of the options)
  • Basic familiarity with Laravel commands and routes

Step-by-Step

  1. Choose a screenshot library. The most common options are spatie/browsershot (which wraps Puppeteer) or laravel-dusk (which uses ChromeDriver). For this guide, we’ll use Browsershot because it’s simple and works well for batch screenshots.
  2. Install Browsershot via Composer. Run composer require spatie/browsershot in your project root.
  3. Install Puppeteer. Browsershot requires Puppeteer to control a headless browser. Run npm install puppeteer in your project root. If you’re on a server without a GUI, ensure all Puppeteer dependencies are installed (see Troubleshooting).
  4. Create a directory for screenshots. In your Laravel project, create a folder like storage/app/public/screenshots. Make sure it’s writable by your web server.
  5. Write a function that captures a single screenshot. Create a helper or use a controller method. Here’s a basic example:
    use Spatie\Browsershot\Browsershot;
    
    function captureScreenshot($url, $path) {
        Browsershot::url($url)
            ->windowSize(1280, 720)
            ->save($path);
    }
        
  6. Create an array of URLs to screenshot. You can hardcode them, read from a database, or accept them as input. For this example, we’ll use a simple array:
    $urls = [
        'https://example.com',
        'https://laravel.com',
        'https://github.com',
    ];
        
  7. Loop through the URLs and capture each screenshot. Use a foreach loop. Save each file with a unique name, like based on the domain or a hash.
    foreach ($urls as $url) {
        $filename = md5($url) . '.png';
        $path = storage_path('app/public/screenshots/' . $filename);
        captureScreenshot($url, $path);
    }
        
  8. Add error handling. Wrap the capture in a try-catch block to handle failures gracefully (e.g., if a site is down). Log the error and continue with the next URL.
    try {
        captureScreenshot($url, $path);
    } catch (\Exception $e) {
        \Log::error("Failed to capture $url: " . $e->getMessage());
    }
        
  9. Make it a reusable Artisan command. Create a command with php artisan make:command CaptureScreenshots. In the handle() method, put the loop. Accept URLs as an argument or option, or read from a config file.
  10. Run the command. Use php artisan screenshots:capture (or whatever you name it). The screenshots will be saved to your storage folder.

Common Mistakes

  • Not installing Puppeteer. Browsershot will throw an error if Puppeteer isn’t installed. Make sure you run npm install puppeteer.
  • Missing system dependencies. Puppeteer needs certain libraries on Linux (e.g., libnss3, libatk). Without them, the browser won’t start.
  • Using the wrong path. The save() method expects a full filesystem path, not a relative URL. Use storage_path() or public_path().
  • Not setting a timeout. Some pages load slowly. Set a timeout to avoid hanging forever: Browsershot::url($url)->timeout(30).
  • Overwriting files. If you use the same filename for multiple URLs, you’ll only get the last one. Use a unique identifier like a hash or timestamp.

Tips

  • Use full-page screenshots. For long pages, add ->fullPage() to capture the entire scrollable area.
  • Set a custom user agent. Some sites block headless browsers. Use ->userAgent('Mozilla/5.0 ...') to mimic a real browser.
  • Wait for JavaScript. If a page renders content dynamically, use ->waitUntilNetworkIdle() or ->delay(1000) to give scripts time to load.
  • Store screenshots on a cloud disk. Instead of local storage, configure a cloud filesystem (e.g., S3) and save there for scalability.
  • Queue the screenshots. For many URLs, use Laravel Queues to process them in the background, preventing timeouts.

Troubleshooting

  • “Puppeteer not found” error. This means Puppeteer isn’t installed or the path is wrong. Run npm install puppeteer and ensure the node_modules folder is in your project root.
  • “Failed to launch the browser process” error. This is usually a missing system library. On Ubuntu, run: sudo apt-get install -y libnss3 libatk-bridge2.0-0 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 libgbm1.
  • Blank or partial screenshots. The page might not have loaded fully. Increase the timeout, use ->waitUntilNetworkIdle(), or add a delay.
  • Permission denied when saving. Ensure the storage directory is writable: chmod -R 775 storage.
  • Memory exhaustion with many URLs. Process URLs in batches (e.g., 10 at a time) or use queues to avoid overwhelming the server.

Frequently Asked Questions

Can I screenshot a localhost URL?

Yes, but the browser runs outside your Laravel app, so it needs to access the site via a reachable URL. Use http://127.0.0.1:8000 if your dev server is running, or use a tool like ngrok for external access.

How can I capture screenshots of pages that require login?

You can use Browsershot::url($url)->authenticate('username', 'password') for HTTP basic auth. For form-based login, you’d need to use a more complex approach with Puppeteer’s evaluate() to fill in forms.

What file formats are supported?

Browsershot supports PNG, JPEG, and WebP. Use ->format('jpeg') or ->format('webp') before saving.

Can I capture screenshots of multiple URLs at once?

Yes, that’s exactly what this guide covers. You loop through the URLs and capture each one sequentially. For better performance, you can use parallel processing with Laravel Queues or pthreads (though not recommended).

How do I get the screenshot as a base64 string instead of a file?

Use Browsershot::url($url)->base64Screenshot() which returns a base64-encoded image string.

Does this work on shared hosting?

Usually not, because Puppeteer requires a Node.js runtime and system libraries that are rarely available on shared hosting. Consider using a VPS or a cloud function instead.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →