Skip to main content

PHP Examples

Copy-paste ready examples for common use cases with the Browser7 PHP SDK.


Basic Examples

Simple Page Render

<?php

require 'vendor/autoload.php';

use Browser7\Browser7Client;

$client = new Browser7Client('b7_your_api_key_here');
$result = $client->render('https://example.com');

echo $result->html;

Geo-Targeted Render

// Target a specific country
$result = $client->render('https://example.com', [
'countryCode' => 'DE'
]);

// Target a specific city
$result = $client->render('https://example.com', [
'countryCode' => 'US',
'city' => 'new.york'
]);

Screenshot Capture

// Viewport screenshot (JPEG, default)
$result = $client->render('https://example.com', [
'includeScreenshot' => true
]);

// Full page PNG screenshot
$result = $client->render('https://example.com', [
'includeScreenshot' => true,
'screenshotFormat' => 'png',
'screenshotFullPage' => true
]);

// Save to file
file_put_contents('screenshot.png', base64_decode($result->screenshot));

Wait Actions

Wait for Element Visibility

use Browser7\WaitAction;

$result = $client->render('https://example.com', [
'waitFor' => [
WaitAction::selector('.product-loaded', 'visible', 15000)
]
]);

$result = $client->render('https://example.com', [
'waitFor' => [
WaitAction::click('.cookie-accept', 5000),
WaitAction::selector('.main-content', 'visible')
]
]);

Wait for Text Content

$result = $client->render('https://shop.example.com/product/123', [
'waitFor' => [
WaitAction::text('In Stock', '.availability', 10000)
]
]);

Multiple Wait Actions Combined

$result = $client->render('https://example.com', [
'waitFor' => [
WaitAction::click('.cookie-banner-accept', 5000),
WaitAction::selector('.content', 'visible'),
WaitAction::text('Data loaded'),
WaitAction::delay(500)
]
]);

CAPTCHA Solving

Auto-Detect and Solve

$result = $client->render('https://example.com', [
'captcha' => 'auto'
]);

Target a Specific CAPTCHA Type

// reCAPTCHA v2
$result = $client->render('https://example.com', ['captcha' => 'recaptcha_v2']);

// reCAPTCHA v3
$result = $client->render('https://example.com', ['captcha' => 'recaptcha_v3']);

// Cloudflare Turnstile
$result = $client->render('https://example.com', ['captcha' => 'turnstile']);

Two-Step CAPTCHA Detection

Check for a CAPTCHA first, then solve only if needed:

// First render - no CAPTCHA solving (fastest)
$result = $client->render('https://example.com');

// Re-render with solving if CAPTCHA was detected but not handled
if (
isset($result->captcha['detected']) &&
$result->captcha['detected'] &&
!$result->captcha['handled']
) {
$result = $client->render('https://example.com', ['captcha' => 'auto']);
}

Advanced Usage

Progress Tracking

$result = $client->render('https://example.com', [
'onProgress' => function (array $event) {
switch ($event['type']) {
case 'started':
echo "Render started: {$event['renderId']}" . PHP_EOL;
break;
case 'polling':
echo "Attempt {$event['attempt']}: {$event['status']}" . PHP_EOL;
break;
case 'completed':
echo "Render completed" . PHP_EOL;
break;
case 'failed':
echo "Render failed" . PHP_EOL;
break;
}
}
]);

Manual Polling (Low-Level API)

// Create the render job
$response = $client->createRender('https://example.com', [
'countryCode' => 'US'
]);
$renderId = $response['renderId'];
echo "Render ID: {$renderId}" . PHP_EOL;

sleep(2);

// Poll manually
for ($attempt = 0; $attempt < 60; $attempt++) {
$result = $client->getRender($renderId);
echo "Attempt " . ($attempt + 1) . ": {$result->status}" . PHP_EOL;

if ($result->status === 'completed') {
echo $result->html;
break;
} elseif ($result->status === 'failed') {
throw new \RuntimeException("Render failed: {$result->error}");
}

sleep($result->retryAfter);
}

Error Handling with Retries

use Browser7\AuthenticationError;
use Browser7\ValidationError;
use Browser7\RenderError;

function renderWithRetry(
Browser7Client $client,
string $url,
array $options = [],
int $maxRetries = 3
): \Browser7\RenderResult {
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
try {
return $client->render($url, $options);
} catch (AuthenticationError $e) {
throw $e; // Don't retry auth errors - fix your API key
} catch (ValidationError $e) {
throw $e; // Don't retry validation errors - fix your request
} catch (RenderError | \RuntimeException $e) {
if ($attempt === $maxRetries - 1) {
throw $e;
}
$wait = 2 ** $attempt; // Exponential backoff: 1s, 2s, 4s
echo "Attempt " . ($attempt + 1) . " failed: {$e->getMessage()}. Retrying in {$wait}s..." . PHP_EOL;
sleep($wait);
}
}
}

$result = renderWithRetry($client, 'https://example.com', ['countryCode' => 'US']);

Batch Processing

$urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3',
];

$results = [];

foreach ($urls as $url) {
try {
$result = $client->render($url);
$results[] = ['url' => $url, 'html' => $result->html];
} catch (\RuntimeException $e) {
$results[] = ['url' => $url, 'error' => $e->getMessage()];
}
}

echo 'Scraped ' . count($results) . ' pages' . PHP_EOL;

Fetch Additional URLs

$result = $client->render('https://example.com', [
'fetchUrls' => [
'https://api.example.com/data.json',
'https://example.com/config.json',
]
]);

foreach ($result->fetchResponses as $response) {
print_r($response);
}

Account Operations

Check Account Balance

$balance = $client->getAccountBalance();

echo "Total: {$balance->totalBalanceFormatted}" . PHP_EOL;
echo "Renders remaining: {$balance->totalBalanceCents}" . PHP_EOL;
echo " Paid: {$balance->breakdown->paid->formatted}" . PHP_EOL;
echo " Free: {$balance->breakdown->free->formatted}" . PHP_EOL;
echo " Bonus: {$balance->breakdown->bonus->formatted}" . PHP_EOL;

Check Balance Before Expensive Operations

$balance = $client->getAccountBalance();

if ($balance->totalBalanceCents < count($urls)) {
throw new \RuntimeException(
"Insufficient balance: {$balance->totalBalanceFormatted}"
);
}

foreach ($urls as $url) {
$result = $client->render($url);
}

Available Regions

$regions = $client->getRegions();

foreach ($regions as $region) {
$status = $region->status === 'active' ? '✓' : '✗';
echo "{$status} {$region->code}: {$region->name}" . PHP_EOL;
}

Real-World Scenarios

E-Commerce Product Scraping

use Browser7\Browser7Client;
use Browser7\WaitAction;

$client = new Browser7Client('b7_your_api_key_here');

$result = $client->render('https://shop.example.com/product/123', [
'countryCode' => 'US',
'city' => 'new.york',
'waitFor' => [
WaitAction::selector('.product-price', 'visible'),
WaitAction::selector('.stock-status', 'visible'),
],
'includeScreenshot' => true,
'screenshotFormat' => 'jpeg',
'screenshotQuality' => 85,
]);

// Save screenshot
file_put_contents('product.jpg', base64_decode($result->screenshot));

echo $result->html;

News Article with Cookie Handling

$result = $client->render('https://news.example.com/article/123', [
'waitFor' => [
WaitAction::click('.gdpr-accept-all', 5000),
WaitAction::selector('article.content', 'visible', 15000),
],
'blockImages' => true // Faster for text content
]);

echo $result->html;

Protected Site with CAPTCHA

$result = $client->render('https://protected.example.com/data', [
'captcha' => 'auto',
'countryCode' => 'US',
'waitFor' => [
WaitAction::selector('.data-table', 'visible', 30000)
]
]);

Laravel Controller Example

<?php

namespace App\Http\Controllers;

use Browser7\Browser7Client;
use Browser7\WaitAction;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class ScrapeController extends Controller
{
private Browser7Client $browser7;

public function __construct()
{
$this->browser7 = new Browser7Client(config('services.browser7.key'));
}

public function scrape(Request $request): JsonResponse
{
$request->validate(['url' => 'required|url']);

try {
$result = $this->browser7->render($request->url, [
'waitFor' => [WaitAction::selector('body', 'visible')],
]);

return response()->json([
'html' => $result->html,
'city' => $result->selectedCity,
]);
} catch (\RuntimeException $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}
}

Best Practices

Performance

// Block images when you only need HTML (default: true)
$result = $client->render('https://example.com', ['blockImages' => true]);

// Use specific CAPTCHA types instead of 'auto' when you know the type
// (single check only - avoids 10-second polling)
$result = $client->render('https://example.com', ['captcha' => 'recaptcha_v2']);

// Viewport-only screenshots are faster than full page
$result = $client->render('https://example.com', [
'includeScreenshot' => true,
'screenshotFullPage' => false // Default - faster
]);

Next Steps