screenshotfreeapi/screenshotfreeapi-php
Composer 安装命令:
composer require screenshotfreeapi/screenshotfreeapi-php
包简介
Official PHP SDK for ScreenshotFreeAPI — screenshot-as-a-service for developers
README 文档
README
Official PHP SDK for ScreenshotFreeAPI — screenshot-as-a-service for developers.
Capture pixel-perfect screenshots of any website, HTML string, or mobile app store listing with a single function call. No headless browser setup required.
- Zero production dependencies (cURL only — built into PHP)
- PHP 8.0+ with readonly properties and named arguments
- Automatic retry with exponential back-off (429 / 5xx)
- Webhook signature verification via
hash_equals - PSR-4 autoloading
Requirements
- PHP 8.0 or higher
ext-curl(enabled in most PHP installations)ext-json(enabled in most PHP installations)
Installation
composer require screenshotfreeapi/screenshotfreeapi-php
Quick Start
use ScreenshotFreeAPI\ScreenshotFreeAPIClient; $client = new ScreenshotFreeAPIClient('sfa_your_api_key_here'); // Capture a screenshot and wait for the result $result = $client->capture('https://stripe.com/pricing'); echo $result['screenshots'][0]['url']; // https://s3.amazonaws.com/snapshots/...?X-Amz-Expires=900
Authentication
API Key (screenshots, jobs, integrations)
Every request is authenticated with your API key via the Authorization: Bearer header. Pass the key to the constructor:
$client = new ScreenshotFreeAPIClient('sfa_your_api_key_here');
Management JWT (billing, workspaces, monitors)
Billing, workspace, and monitor endpoints require a short-lived JWT obtained by trading your email and password:
$tokenResponse = $client->auth->token('you@example.com', 'your_password'); $jwt = $tokenResponse['token']; // Use the JWT for billing calls $plan = $client->billing->plan($jwt);
Screenshot Types
Web Screenshot
Capture any public URL. Supports AI-targeted cropping, custom dimensions, full-page capture, PDF output, and more.
// Basic $job = $client->screenshots->web(['url' => 'https://example.com']); $result = $client->screenshots->wait($job['jobId']); // With options $job = $client->screenshots->web([ 'url' => 'https://stripe.com/pricing', 'description' => 'the pricing comparison table', // AI targeting 'format' => 'png', 'fullPage' => true, 'dimensions' => ['width' => 1440, 'height' => 900], 'blockAds' => true, 'acceptCookies' => true, 'webhookUrl' => 'https://your-app.com/webhook', ]); // Or capture and wait in one call $result = $client->screenshots->webAndWait([ 'url' => 'https://github.com', 'format' => 'jpeg', ]); echo $result['screenshots'][0]['url'];
Mobile App Screenshot
Fetch screenshots from the App Store and/or Google Play, or emulate a device.
$result = $client->screenshots->mobileAndWait([ 'appName' => 'Instagram', 'platform' => 'both', // 'ios', 'android', or 'both' 'includeStoreListing' => true, 'deviceEmulation' => 'iPhone 12', ]); foreach ($result['screenshots'] as $screenshot) { echo $screenshot['url'] . PHP_EOL; }
HTML String Rendering
Render a raw HTML string (email template, report card, certificate, etc.) to a screenshot.
$html = '<html><body style="background:hotpink;padding:40px"><h1>Hello!</h1></body></html>'; $result = $client->screenshots->htmlAndWait([ 'html' => $html, 'format' => 'png', 'dimensions' => ['width' => 800, 'height' => 400], ]); echo $result['screenshots'][0]['url'];
Convenience Method
$client->capture() is a shorthand for webAndWait():
$result = $client->capture('https://news.ycombinator.com', [ 'format' => 'png', 'fullPage' => true, ]);
Manual Polling
For fine-grained control, submit a job and poll it yourself:
use ScreenshotFreeAPI\Exceptions\JobFailedException; use ScreenshotFreeAPI\Exceptions\JobTimeoutException; // Submit (non-blocking, returns immediately with jobId) $job = $client->screenshots->web([ 'url' => 'https://vercel.com', 'webhookUrl' => 'https://your-app.com/webhook', // optional ]); echo "Job ID: " . $job['jobId'] . PHP_EOL; echo "Estimated: " . $job['estimatedSeconds'] . "s" . PHP_EOL; // Poll status manually while (true) { $status = $client->jobs->status($job['jobId']); echo "Status: " . $status['status'] . " (" . $status['progress'] . "%)"; if ($status['status'] === 'completed') { $result = $client->jobs->result($job['jobId']); echo $result['screenshots'][0]['url']; break; } if ($status['status'] === 'failed') { echo "Failed: " . $status['error']; break; } sleep(2); }
Polling with progress callback
$result = $client->screenshots->wait( jobId: $job['jobId'], pollIntervalMs: 2000, timeoutMs: 120000, onProgress: function (array $status): void { printf("[%s] %d%%\n", $status['status'], $status['progress']); } );
Error Handling
All exceptions extend ScreenshotFreeAPI\Exceptions\ScreenshotFreeAPIException which extends \RuntimeException.
use ScreenshotFreeAPI\Exceptions\AuthenticationException; use ScreenshotFreeAPI\Exceptions\ForbiddenException; use ScreenshotFreeAPI\Exceptions\JobFailedException; use ScreenshotFreeAPI\Exceptions\JobTimeoutException; use ScreenshotFreeAPI\Exceptions\NotFoundException; use ScreenshotFreeAPI\Exceptions\PaymentRequiredException; use ScreenshotFreeAPI\Exceptions\QuotaExceededException; use ScreenshotFreeAPI\Exceptions\RateLimitException; use ScreenshotFreeAPI\Exceptions\ScreenshotFreeAPIException; use ScreenshotFreeAPI\Exceptions\ValidationException; try { $result = $client->capture('https://example.com'); } catch (AuthenticationException $e) { // 401 — invalid or missing API key echo "Auth error: " . $e->getMessage(); } catch (ForbiddenException $e) { // 403 — key revoked or account suspended echo "Forbidden: " . $e->getMessage(); } catch (PaymentRequiredException $e) { // 402 — subscription cancelled or payment overdue echo "Payment required: " . $e->getMessage(); } catch (QuotaExceededException $e) { // 429 (quota variant) — monthly screenshot limit reached echo "Quota exhausted. Upgrade your plan."; } catch (RateLimitException $e) { // 429 (rate limit variant) — too many requests per minute echo "Rate limited. Retry after " . $e->getRetryAfter() . "s"; sleep($e->getRetryAfter()); } catch (ValidationException $e) { // 400 — request body failed validation echo "Validation error: " . $e->getMessage(); print_r($e->getDetails()); } catch (NotFoundException $e) { // 404 — job not found or not owned by this key echo "Not found: " . $e->getMessage(); } catch (JobFailedException $e) { // Job reached FAILED status during polling echo "Job " . $e->getJobId() . " failed: " . $e->getReason(); } catch (JobTimeoutException $e) { // Polling timed out before job completed echo "Job " . $e->getJobId() . " timed out after " . $e->getTimeoutMs() . "ms"; } catch (ScreenshotFreeAPIException $e) { // Catch-all for any other ScreenshotFreeAPI error (5xx etc.) echo "API error [HTTP " . $e->getStatusCode() . "]: " . $e->getMessage(); }
Billing
// List plans (no auth required) $plans = $client->billing->plans(); // Current plan and usage (JWT required) $jwt = $client->auth->token('you@example.com', 'password')['token']; $plan = $client->billing->plan($jwt); echo $plan['tier'] . ": " . $plan['screenshotsUsed'] . " used"; // 30-day usage history $usage = $client->billing->usage($jwt); // Upgrade plan (returns Flutterwave checkout URL) $checkout = $client->billing->upgrade($jwt, ['plan' => 'GROWTH']); echo $checkout['checkoutUrl']; // Cancel subscription $client->billing->cancel($jwt);
Team Workspaces
$jwt = $client->auth->token('you@example.com', 'password')['token']; // Create workspace $ws = $client->workspaces->create($jwt, ['name' => 'Acme Team']); // List workspaces $list = $client->workspaces->list($jwt); // Invite a member $client->workspaces->invite($jwt, $ws['id'], 'colleague@acme.com', 'member'); // Change role $client->workspaces->updateMemberRole($jwt, $ws['id'], $userId, 'admin'); // Remove member $client->workspaces->removeMember($jwt, $ws['id'], $userId);
App Monitors
$jwt = $client->auth->token('you@example.com', 'password')['token']; // Create a monitor (cron: every hour) $monitor = $client->monitors->create($jwt, [ 'appName' => 'Instagram', 'platform' => 'both', 'schedule' => '0 * * * *', 'webhookUrl' => 'https://your-app.com/monitor-webhook', ]); // List monitors $monitors = $client->monitors->list($jwt); // Fetch run history with diffs $history = $client->monitors->history($jwt, $monitor['id'], ['limit' => 10]); // Delete a monitor $client->monitors->delete($jwt, $monitor['id']);
Zapier Integration
// Register a webhook for Zapier $sub = $client->integrations->zapierSubscribe( 'https://hooks.zapier.com/hooks/catch/xxx/yyy', 'screenshot.completed' ); // Get a sample payload for Zap setup $sample = $client->integrations->zapierTriggerSample('screenshot.completed'); // Unsubscribe $client->integrations->zapierUnsubscribe($sub['subscriptionId']);
Webhooks
When a screenshot job completes (or fails) the server can POST a signed event to your webhookUrl. Always verify the signature before processing.
Plain PHP
$rawBody = file_get_contents('php://input'); $sig = $_SERVER['HTTP_X_SCREENSHOTFREE_SIGNATURE'] ?? ''; $secret = $_ENV['SCREENSHOTFREEAPI_WEBHOOK_SECRET']; use ScreenshotFreeAPI\Webhooks; if (!Webhooks::verifySignature($rawBody, $sig, $secret)) { http_response_code(401); exit('Invalid signature'); } $event = json_decode($rawBody, true); if ($event['event'] === 'screenshot.completed') { $jobId = $event['jobId']; // fetch result, save to DB, notify user, etc. } http_response_code(200);
Laravel Middleware
// app/Http/Middleware/VerifyScreenshotFreeAPIWebhook.php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use ScreenshotFreeAPI\Webhooks; class VerifyScreenshotFreeAPIWebhook { public function handle(Request $request, Closure $next): mixed { $sig = $request->header('X-ScreenshotFree-Signature', ''); $secret = config('services.screenshotfreeapi.webhook_secret'); if (!Webhooks::verifySignature($request->getContent(), $sig, $secret)) { abort(401, 'Invalid ScreenshotFreeAPI webhook signature.'); } return $next($request); } }
Register in bootstrap/app.php (Laravel 11+) or app/Http/Kernel.php:
// Route definition Route::post('/webhooks/screenshot-events', ScreenshotFreeAPIWebhookController::class) ->middleware(VerifyScreenshotFreeAPIWebhook::class);
Configuration
$client = new ScreenshotFreeAPIClient( apiKey: 'sfa_your_key', baseUrl: 'https://api.screenshotfreeapi.com', // override for testing/proxy timeout: 30, // cURL timeout in seconds maxRetries: 3 // max retry attempts (429 + 5xx) );
Retry behaviour
The SDK automatically retries failed requests on HTTP 429 and 5xx responses using exponential back-off:
| Attempt | Delay |
|---|---|
| 1st retry | 1 s |
| 2nd retry | 2 s |
| 3rd retry | 4 s |
For HTTP 429 responses the Retry-After header value is used when present.
Health Check
$status = $client->health(); // ['status' => 'ok', 'version' => '2.0.0', ...]
Running Tests
composer install ./vendor/bin/phpunit tests/
License
MIT — see LICENSE for details.
Support
- Documentation: https://screenshotfreeapi.com/docs
- Email: support@screenshotfreeapi.com
- GitHub Issues: https://github.com/chinkauchenna2021/screenshotfreeapi-php/issues
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-20