Screenshot API for PHP: Complete Integration Guide
PHP powers a substantial portion of the web, including a large fraction of SaaS platforms, CMS systems, and e-commerce applications. If you are building on Laravel, Symfony, or plain PHP and need screenshot, scraping, or PDF generation capabilities, SnapAPI provides a clean REST API that integrates in minutes. This guide covers everything from a basic cURL integration to a production-ready Laravel service class with response caching and background job handling.
Basic Integration with cURL
The simplest way to call SnapAPI from PHP is using the built-in cURL extension. The following example captures a screenshot and saves the result URL to a variable:
<?php
$apiKey = "YOUR_SNAPAPI_KEY";
$url = "https://example.com";
$ch = curl_init("https://snapapi.pics/api/screenshot");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: " . $apiKey,
],
CURLOPT_POSTFIELDS => json_encode([
"url" => $url,
"full_page" => true,
"format" => "png",
]),
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "Screenshot URL: " . $data["url"];
?>Using Guzzle HTTP Client
For Laravel and Symfony applications already using Guzzle, the integration is even cleaner:
use GuzzleHttp\Client;
$client = new Client(["base_uri" => "https://snapapi.pics"]);
$response = $client->post("/api/screenshot", [
"headers" => [
"X-API-Key" => config("services.snapapi.key"),
"Content-Type" => "application/json",
],
"json" => [
"url" => "https://example.com",
"full_page" => true,
"format" => "png",
],
]);
$data = json_decode($response->getBody(), true);
$screenshotUrl = $data["url"];Laravel Service Class Pattern
For production Laravel applications, wrapping SnapAPI in a dedicated service class gives you a clean interface for the rest of your application to consume:
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
class SnapApiService
{
private string $apiKey;
private string $baseUrl = "https://snapapi.pics";
public function __construct()
{
$this->apiKey = config("services.snapapi.key");
}
public function screenshot(string $url, array $options = []): string
{
$cacheKey = "screenshot:" . md5($url . serialize($options));
return Cache::remember($cacheKey, now()->addMinutes(15), function () use ($url, $options) {
$response = Http::withHeaders([
"X-API-Key" => $this->apiKey,
])->post($this->baseUrl . "/api/screenshot", array_merge([
"url" => $url,
"full_page" => false,
"format" => "png",
], $options));
return $response->json("url");
});
}
public function extract(string $url, array $fields): array
{
$response = Http::withHeaders([
"X-API-Key" => $this->apiKey,
])->post($this->baseUrl . "/api/extract", [
"url" => $url,
"fields" => $fields,
]);
return $response->json("data", []);
}
public function pdf(string $url): string
{
$response = Http::withHeaders([
"X-API-Key" => $this->apiKey,
])->post($this->baseUrl . "/api/screenshot", [
"url" => $url,
"format" => "pdf",
"full_page" => true,
]);
return $response->json("url");
}
}Background Jobs with Laravel Queue
For high-volume screenshot workloads, synchronous API calls will block your web workers and degrade response times. Dispatch screenshot requests to a Laravel queue instead:
<?php
namespace App\Jobs;
use App\Services\SnapApiService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class CaptureScreenshot implements ShouldQueue
{
use Queueable;
public function __construct(
private string $url,
private int $recordId,
private string $recordType
) {}
public function handle(SnapApiService $snapApi): void
{
$screenshotUrl = $snapApi->screenshot($this->url, ["full_page" => true]);
// Store result against the record
app($this->recordType)->find($this->recordId)
->update(["screenshot_url" => $screenshotUrl]);
}
}
// Dispatch from your controller:
CaptureScreenshot::dispatch($url, $product->id, Product::class)->onQueue("screenshots");PDF Generation for Reports
Generating PDF reports from web pages is a common requirement for SaaS dashboards, invoices, and compliance documentation. SnapAPI handles this natively:
// Generate a PDF from an invoice page
$snapApi = app(SnapApiService::class);
$pdfUrl = $snapApi->pdf("https://yourapp.com/invoices/" . $invoice->id);
// Return as a download response
return response()->stream(function () use ($pdfUrl) {
$stream = fopen($pdfUrl, "r");
fpassthru($stream);
fclose($stream);
}, 200, [
"Content-Type" => "application/pdf",
"Content-Disposition" => "attachment; filename=invoice-" . $invoice->id . ".pdf",
]);Adding SnapAPI Key to Laravel Config
Store your API key in .env and reference it via the services config file:
// .env
SNAPAPI_KEY=your_api_key_here
// config/services.php
"snapapi" => [
"key" => env("SNAPAPI_KEY"),
],Error Handling and Retries
Production integrations need graceful error handling. SnapAPI returns standard HTTP status codes: 200 for success, 400 for invalid parameters, 401 for invalid API keys, and 429 for rate limit hits. Handle these in your service class:
public function screenshot(string $url, array $options = []): ?string
{
try {
$response = Http::withHeaders(["X-API-Key" => $this->apiKey])
->retry(3, 1000)
->post($this->baseUrl . "/api/screenshot", array_merge([
"url" => $url, "format" => "png"
], $options));
if ($response->successful()) {
return $response->json("url");
}
Log::error("SnapAPI error", [
"status" => $response->status(),
"body" => $response->body(),
]);
return null;
} catch (\Exception $e) {
Log::error("SnapAPI exception: " . $e->getMessage());
return null;
}
}Testing the Integration
Use Http::fake() in your Laravel tests to avoid real API calls during CI runs:
Http::fake([
"snapapi.pics/*" => Http::response([
"url" => "https://cdn.snapapi.pics/screenshots/test.png",
"captured_at" => "2026-04-04T10:00:00Z",
], 200),
]);
$screenshotUrl = app(SnapApiService::class)->screenshot("https://example.com");
$this->assertEquals("https://cdn.snapapi.pics/screenshots/test.png", $screenshotUrl);Getting Started
Create your free SnapAPI account at snapapi.pics/dashboard. The free plan provides 200 screenshots per month — more than enough to build and validate a complete PHP integration. For production workloads, the Starter plan ($19/month) provides 5,000 monthly captures, and the Growth plan ($79/month) scales to 50,000 with extract and scrape endpoints included.
The PHP SDK is also available on GitHub at github.com/Sleywill/snapapi-php and installable via Composer: composer require snapapi/snapapi-php. The SDK wraps all endpoints with typed method signatures, handles retries automatically, and includes full PHPDoc coverage for IDE autocompletion.