PHPackages                             screenshotfreeapi/screenshotfreeapi-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. screenshotfreeapi/screenshotfreeapi-php

ActiveLibrary[API Development](/categories/api)

screenshotfreeapi/screenshotfreeapi-php
=======================================

Official PHP SDK for ScreenshotFreeAPI — screenshot-as-a-service for developers

v1.0.0(today)00MITPHPPHP &gt;=8.0

Since Jun 20Pushed todayCompare

[ Source](https://github.com/chinkauchenna2021/screenshotfreeapi-php)[ Packagist](https://packagist.org/packages/screenshotfreeapi/screenshotfreeapi-php)[ Docs](https://screenshotfreeapi.com)[ RSS](/packages/screenshotfreeapi-screenshotfreeapi-php/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (1)Versions (2)Used By (0)

ScreenshotFreeAPI PHP SDK
=========================

[](#screenshotfreeapi-php-sdk)

Official PHP SDK for [ScreenshotFreeAPI](https://screenshotfreeapi.com) — 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
------------

[](#requirements)

- PHP 8.0 or higher
- `ext-curl` (enabled in most PHP installations)
- `ext-json` (enabled in most PHP installations)

---

Installation
------------

[](#installation)

```
composer require screenshotfreeapi/screenshotfreeapi-php
```

---

Quick Start
-----------

[](#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
--------------

[](#authentication)

### API Key (screenshots, jobs, integrations)

[](#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)

[](#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
----------------

[](#screenshot-types)

### Web Screenshot

[](#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

[](#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

[](#html-string-rendering)

Render a raw HTML string (email template, report card, certificate, etc.) to a screenshot.

```
$html = 'Hello!';

$result = $client->screenshots->htmlAndWait([
    'html'       => $html,
    'format'     => 'png',
    'dimensions' => ['width' => 800, 'height' => 400],
]);

echo $result['screenshots'][0]['url'];
```

---

Convenience Method
------------------

[](#convenience-method)

`$client->capture()` is a shorthand for `webAndWait()`:

```
$result = $client->capture('https://news.ycombinator.com', [
    'format'   => 'png',
    'fullPage' => true,
]);
```

---

Manual Polling
--------------

[](#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

[](#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
--------------

[](#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
-------

[](#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
---------------

[](#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
------------

[](#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
------------------

[](#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
--------

[](#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

[](#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

[](#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
-------------

[](#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

[](#retry-behaviour)

The SDK automatically retries failed requests on HTTP 429 and 5xx responses using exponential back-off:

AttemptDelay1st retry1 s2nd retry2 s3rd retry4 sFor HTTP 429 responses the `Retry-After` header value is used when present.

---

Health Check
------------

[](#health-check)

```
$status = $client->health();
// ['status' => 'ok', 'version' => '2.0.0', ...]
```

---

Running Tests
-------------

[](#running-tests)

```
composer install
./vendor/bin/phpunit tests/
```

---

License
-------

[](#license)

MIT — see [LICENSE](LICENSE) for details.

---

Support
-------

[](#support)

- Documentation:
- Email:
- GitHub Issues:

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity38

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/89edc115d8ab315db0d1d2da3c10ab411719027c69c1422d5d35e743135b30fb?d=identicon)[screenshotfreeapi](/maintainers/screenshotfreeapi)

---

Top Contributors

[![chinkauchenna2021](https://avatars.githubusercontent.com/u/84646759?v=4)](https://github.com/chinkauchenna2021 "chinkauchenna2021 (1 commits)")

---

Tags

apisdkscreenshotplaywrightweb capturescreenshotfreeapi

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/screenshotfreeapi-screenshotfreeapi-php/health.svg)

```
[![Health](https://phpackages.com/badges/screenshotfreeapi-screenshotfreeapi-php/health.svg)](https://phpackages.com/packages/screenshotfreeapi-screenshotfreeapi-php)
```

###  Alternatives

[deepseek-php/deepseek-php-client

deepseek PHP client is a robust and community-driven PHP client library for seamless integration with the Deepseek API, offering efficient access to advanced AI and data processing capabilities.

46784.5k5](/packages/deepseek-php-deepseek-php-client)[jstolpe/instagram-graph-api-php-sdk

Instagram Graph API PHP SDK

138106.8k2](/packages/jstolpe-instagram-graph-api-php-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
