Updated February 2026 · 8 min read

Website Screenshot API
for PHP

PHP doesn't have a built-in way to render web pages. To capture website screenshots, you either run a headless browser on your server or call an external API. Here are working examples for both approaches.

1. GrabShot API with cURL

The simplest way. No browser to install, no dependencies beyond PHP's built-in cURL extension. One function, works on any PHP hosting.

<?php

function screenshot(string $url, string $output = 'screenshot.webp'): void
{
    $apiKey = 'YOUR_API_KEY'; // Free at grabshot.dev
    
    $params = http_build_query([
        'url'    => $url,
        'format' => 'webp',
        'width'  => '1440',
        'apiKey' => $apiKey,
    ]);
    
    $ch = curl_init("https://grabshot.dev/v1/screenshot?{$params}");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    
    $image = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    if ($httpCode !== 200) {
        throw new RuntimeException("Screenshot failed: HTTP {$httpCode}");
    }
    
    file_put_contents($output, $image);
    echo "Saved " . strlen($image) . " bytes to {$output}\n";
}

screenshot('https://github.com');

Works on: Any PHP 7.4+ hosting, shared hosting, VPS, Laravel Forge, Docker. No Chrome needed.

2. GrabShot with Guzzle (Laravel / Symfony)

If you're using a framework, Guzzle is likely already in your project.

composer require guzzlehttp/guzzle
<?php

use GuzzleHttp\Client;

function screenshot(string $url, string $output = 'screenshot.webp'): void
{
    $client = new Client(['timeout' => 30]);
    
    $response = $client->get('https://grabshot.dev/v1/screenshot', [
        'query' => [
            'url'    => $url,
            'format' => 'webp',
            'width'  => '1440',
            'apiKey' => env('GRABSHOT_API_KEY'), // .env file
        ],
    ]);
    
    file_put_contents($output, $response->getBody());
}

// In a Laravel controller:
public function captureScreenshot(Request $request)
{
    $url = $request->validate(['url' => 'required|url'])['url'];
    
    $client = new Client(['timeout' => 30]);
    $response = $client->get('https://grabshot.dev/v1/screenshot', [
        'query' => [
            'url'         => $url,
            'format'      => 'png',
            'width'       => '1440',
            'deviceFrame' => 'macbook-air',
            'aiCleanup'   => 'true',
            'apiKey'      => config('services.grabshot.key'),
        ],
    ]);
    
    return response($response->getBody())
        ->header('Content-Type', 'image/png')
        ->header('Content-Disposition', 'inline; filename="screenshot.png"');
}

3. Self-Hosted with chrome-php

If you need to interact with pages (fill forms, click buttons) or want full local control, chrome-php/chrome runs headless Chrome from PHP.

composer require chrome-php/chrome
<?php

use HeadlessChromium\BrowserFactory;

$browserFactory = new BrowserFactory('google-chrome');

$browser = $browserFactory->createBrowser([
    'headless'      => true,
    'windowSize'    => [1440, 900],
    'noSandbox'     => true,
    'customFlags'   => ['--disable-gpu'],
]);

try {
    $page = $browser->createPage();
    $page->navigate('https://github.com')->waitForNavigation();
    
    $screenshot = $page->screenshot([
        'format'  => 'png',
        'quality' => 90,
    ]);
    
    $screenshot->saveToFile('github.png');
    echo "Screenshot saved\n";
} finally {
    $browser->close();
}

Pros: Full browser control, free, can interact with pages.
Cons: Needs Chrome installed on server (not available on shared hosting). Uses 300-500MB RAM. Requires proc_open which many hosts disable.

WordPress Integration

Using GrabShot with WordPress (no plugin needed):

<?php
// In your theme's functions.php or a custom plugin

function grabshot_screenshot(string $url): string|false
{
    $api_key = get_option('grabshot_api_key');
    
    $response = wp_remote_get(
        add_query_arg([
            'url'    => $url,
            'format' => 'webp',
            'width'  => '1200',
            'apiKey' => $api_key,
        ], 'https://grabshot.dev/v1/screenshot'),
        ['timeout' => 30]
    );
    
    if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
        return false;
    }
    
    // Save to uploads directory
    $upload_dir = wp_upload_dir();
    $filename = 'screenshot-' . md5($url) . '.webp';
    $filepath = $upload_dir['path'] . '/' . $filename;
    
    file_put_contents($filepath, wp_remote_retrieve_body($response));
    
    return $upload_dir['url'] . '/' . $filename;
}

// Usage in a template:
$screenshot_url = grabshot_screenshot('https://example.com');
if ($screenshot_url) {
    echo '<img src="' . esc_url($screenshot_url) . '" alt="Screenshot">';
}

Comparison

Feature GrabShot API chrome-php
Works on shared hostingYesNo
Needs Chrome installedNoYes
RAM usageMinimal300-500MB
Device frame mockupsBuilt-inNo
AI popup removalYesManual scripting
Page interactionNoFull
CostFree tier, then $9/moServer costs

See it in action

Try GrabShot right now — paste any URL and get a screenshot instantly. No signup needed.

Try Free Screenshot Tool →