定制 screenshotfreeapi/screenshotfreeapi-php 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

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

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-20

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固