PHP
Offizieller PHP-Client für die Crawlbase-Plattform. PSR-kompatibel, per Composer installierbar, funktioniert mit PHP 7.4+ - dasselbe Package, jede API, sinnvolle Defaults.
Wie das SDK aufgebaut ist
Das PHP SDK ist ein dünner Wrapper um dieselbe HTTP-API, die in der API-Referenz dokumentiert ist. Jeder Crawling API-Parameter, den Sie bei einem rohen HTTP-Aufruf als Query-String anhängen würden, ist im SDK als Schlüssel im Options-Array erreichbar - Namen, Defaults und Verhalten sind eins zu eins abgebildet. Es gibt keinen Parameter, den das SDK hinzufügt; es gibt keinen Parameter, den es versteckt.
Was Sie davon haben, es anstelle von cURL oder Guzzle direkt zu nutzen:
- URL-Encoding, Parametervalidierung und Response-Parsing sind out of the box geregelt.
- PSR-4-Autoloading - ohne Aufwand in jedes moderne PHP-Framework (Laravel, Symfony, Slim) integrierbar.
- Eine einzige Client-Klasse pro Crawlbase-API, alle mit derselben Konstruktor-/Aufruf-Signatur.
- Sinnvolle Defaults (90 Sekunden Timeout, automatisches JSON-Parsing von
format=json-Responses, UTF-8-kodierte Bodies).
Quellcode auf github.com/crawlbase/crawlbase-php. Issues und PRs willkommen.
Installation
Aktuelle Version auf Packagist. Erfordert PHP 7.4+; getestet bis PHP 8.3.
composer require crawlbase/crawlbase
# Or add to composer.json directly:
# "crawlbase/crawlbase": "^1.0"Authentifizierung
Jede Crawlbase-API authentifiziert sich über dasselbe Token-Modell. Auf einem einzigen Konto existieren zwei Token-Typen:
- Normal Token (TCP) - für statisches HTML, JSON-Endpoints, alles, was keinen Browser benötigt. Schneller und günstiger.
- JavaScript Token
- für SPAs, lazy geladene Feeds, alles, was Inhalte hinter clientseitigem Rendering versteckt. Erforderlich, um
page_wait,ajax_wait,scrollundcss_click_selectorzu verwenden.
Verwenden Sie in der Produktion Umgebungsvariablen (oder die Konfiguration Ihres Frameworks - Laravel config(), Symfony-Parameter). Das SDK liest selbst keine Env-Variablen aus - das ist Absicht, damit Sie die Kontrolle darüber behalten, woher die Credentials kommen. Muster:
<?php
require 'vendor/autoload.php';
use Crawlbase\CrawlingAPI;
// Pick the right token at instantiation; the SDK doesn't switch
// tokens per-call, so keep two clients if you alternate.
$api = new CrawlingAPI(['token' => getenv('CRAWLBASE_TOKEN')]);
$js = new CrawlingAPI(['token' => getenv('CRAWLBASE_JS_TOKEN')]);
$api->get('https://github.com/anthropic');
$js->get('https://feed.example.com', ['page_wait' => 2000]);Vollständiges Token-Modell und Dashboard-Pfade auf der Seite Authentication.
Schnellstart
Drei Zeilen vom Autoload bis zum gecrawlten HTML:
<?php
require 'vendor/autoload.php';
$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_TOKEN']);
$res = $api->get('https://github.com/anthropic');
if ($res->statusCode == 200) {
echo $res->body;
}Verzweigen Sie auf ->statusCode (der HTTP-Status des SDK gegenüber Crawlbase) und ->headers->pc_status (das Crawlbase-Urteil - siehe Fehler unten), wenn Sie entscheiden, ob erneut versucht werden soll. Übergeben Sie ['format' => 'json'], um einen JSON-Envelope statt des rohen Seiteninhalts zu erhalten.
Alle APIs in einem Paket
Jede Crawlbase-API hat eine passende Client-Klasse. Derselbe Konstruktor, dieselben get-/post-Verben.
<?php
use Crawlbase\{CrawlingAPI, ScraperAPI, LeadsAPI, ScreenshotsAPI, StorageAPI};
$token = ['token' => 'YOUR_TOKEN'];
$crawl = new CrawlingAPI($token); // general-purpose page fetch
$scraper = new ScraperAPI($token); // parsed JSON for supported sites
$leads = new LeadsAPI($token); // domain-scoped email extraction (legacy)
$shots = new ScreenshotsAPI($token); // screenshots of any URL
$storage = new StorageAPI($token); // Cloud Storage CRUD
// Push high-volume async jobs to the Enterprise Crawler via the Crawling API:
// $api->get($url, ['async' => true, 'callback' => '...', 'crawler' => 'YourCrawler']).
// See /docs/crawler for the queue workflow.Gängige Muster
JavaScript-Rendering
Für SPAs, lazy-geladene Feeds und Seiten, deren initiales HTML leer ist, instanziieren Sie mit dem JavaScript token und übergeben eine beliebige Kombination aus page_wait, ajax_wait, scroll und css_click_selector. Reihenfolge zum Mitdenken: ein fester Wait, dann Network-Idle, dann Scroll fürs Lazy-Loading, dann Klick für jedes Gating-UI-Element.
$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_JS_TOKEN']);
$res = $api->get('https://spa.example.com', [
'page_wait' => 2000,
'ajax_wait' => true,
'scroll' => true,
]);Eingebauten Scraper verwenden
Auf unterstützten Sites entfällt der Parser komplett. Übergeben Sie 'scraper' => 'NAME', und der Response-Body wird zu einem JSON-String mit den strukturierten Feldern, die auf der Seite des jeweiligen Scrapers dokumentiert sind.
<?php
use Crawlbase\ScraperAPI;
$api = new ScraperAPI(['token' => 'YOUR_TOKEN']);
$res = $api->get('https://www.amazon.com/dp/1098145356',
['scraper' => 'amazon-product-details']);
$data = json_decode($res->body, true);
echo $data['name'] . ' - ' . $data['price'];Geo-Routing
Übergeben Sie 'country' => 'ISO', um den Crawl über die Exit-Nodes des jeweiligen Landes zu leiten. Verwenden Sie das immer dann, wenn das Ziel anhand der IP lokalisierte Inhalte ausliefert.
$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_TOKEN']);
// Hit the German Amazon catalog from a German residential IP
$res = $api->get('https://www.amazon.com/dp/1098145356', ['country' => 'DE']);Retry mit Backoff
Empfohlene Retry-Form: exponentielles Backoff, gedeckelt auf 3–5 Versuche, Retry nur bei transienten Fehlern (5xx oder leerem Body), kein Retry bei 4xx.
<?php
use Crawlbase\CrawlingAPI;
function crawl(CrawlingAPI $api, string $url, int $attempts = 5) {
for ($i = 0; $i < $attempts; $i++) {
$res = $api->get($url);
if ($res->statusCode === 200 && (int) $res->headers->pc_status === 200) {
return $res;
}
if ($res->statusCode >= 400 && $res->statusCode < 500) {
throw new RuntimeException("client error {$res->statusCode}: $url");
}
usleep((int) (mt_rand() / mt_getrandmax() * pow(2, $i) * 1_000_000));
}
throw new RuntimeException("Failed: $url");
}Async-Crawls und Webhooks
Fire-and-forget-Modus. Der SDK-Aufruf kehrt sofort mit einer rid zurück; Crawlbase POSTet das Ergebnis an Ihre Callback-URL, sobald die Seite bereit ist. Nützlich für Batch-Jobs und langsame Ziele.
$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_TOKEN']);
$res = $api->get('https://example.com', [
'async' => true,
'callback' => 'https://your-app.com/webhook',
]);
$rid = $res->rid; // correlate the eventual webhook delivery
// Your Laravel / Symfony / Slim webhook receives a POST with:
// { rid, url, original_status, pc_status, body }Für sehr hohe Volumina (Millionen von URLs) verwenden Sie den Enterprise Crawler, der vor derselben Async-Pipeline sitzt.
Sticky Sessions
Manche Flows benötigen über mehrere Aufrufe hinweg dieselbe Residential-IP. Übergeben Sie cookies_session mit einem stabilen Identifier, und Crawlbase verwendet etwa 30 Minuten lang denselben Exit-Node.
$api = new \Crawlbase\CrawlingAPI(['token' => 'YOUR_JS_TOKEN']);
$session = "checkout-{$userId}";
$api->get('https://shop.example.com/cart', ['cookies_session' => $session]);
$api->get('https://shop.example.com/checkout', ['cookies_session' => $session]);
$api->get('https://shop.example.com/confirm', ['cookies_session' => $session]);Fehler & Retries
Die Plattform liefert bei jeder Response zwei Status-Codes: den eigenen ->statusCode des SDK (HTTP-Status der Anfrage an Crawlbase selbst) und ->headers->pc_status (das Urteil von Crawlbase zum Ziel - siehe die Fehlertabelle der Crawling API für die vollständige Liste). Verzweigen Sie für Retry-Entscheidungen immer auf ->headers->pc_status - ein Ziel kann 200 mit leerem Body zurückgeben, in dem Fall ist ->statusCode 200, aber ->headers->pc_status 520.
$res = $api->get($url);
$pc = (int) $res->headers->pc_status;
switch (true) {
case $pc === 200:
use_body($res->body);
break;
case in_array($pc, [520, 525], true):
// 520 = empty body, 525 = anti-bot couldn't be solved.
// Switch to JS token and retry.
retry_with_js_token($url);
break;
case in_array($pc, [521, 522, 523], true):
// Target unreachable or timed out. Retry with backoff.
schedule_retry($url);
break;
default:
$logger->error('crawl failed', ['url' => $url, 'pc_status' => $pc]);
}Alle Retries gegenüber der Plattform sind kostenlos - nur erfolgreiche Responses (pc_status: 200) zählen auf Ihr Kontingent.
Performance & Best Practices
- Verwenden Sie pro Token einen einzigen Client wieder. Bauen Sie ihn einmal beim Start der App auf (Laravel-Service-Provider, Symfony-Service-Container) und injizieren Sie ihn überall - jede Instanz öffnet ihre eigene Verbindung.
- Verwenden Sie das günstigste Token, das funktioniert. Verwenden Sie nicht standardmäßig den JavaScript token «zur Sicherheit» - Requests mit dem Normal token sind schneller und beanspruchen weniger Concurrency. Wechseln Sie erst dann zu JS, wenn die Normal-Response leer oder durch Anti-Bot blockiert ist.
- Bevorzugen Sie
ajax_waitgegenüberpage_wait. Feste Wartezeiten verbrauchen Concurrency bei jedem Request, auch bei schnellen. - Für Batch-Jobs: async + Webhook oder Push an den Enterprise Crawler. Queue-Worker, die das SDK synchron aufrufen, sättigen Ihr Concurrency-Limit; async + Webhook gibt den Slot frei, sobald ein Request in die Queue gelegt ist.
- Behalten Sie den Response-Header
remainingim Auge. Er enthält die Anzahl der Concurrency-Slots, die Ihnen noch zur Verfügung stehen.
Methodenreferenz
Alle Client-Klassen teilen sich dieselbe Oberfläche. Der Konstruktor nimmt ein Options-Array entgegen; die Verben spiegeln die zugrundeliegenden HTTP-Methoden wider.
'timeout' in Sekunden (Standard 90).$options bildet jeden Crawling API-Parameter auf seinen Wert ab.$data ist der Body - übergeben Sie ein Array für form-encoded, einen String für raw.Response-Form - öffentliche Properties auf dem Response-Objekt, das von jedem Verb zurückgegeben wird:
format=json / scraper= verwendet wurde).->headers->pc_status: Crawlbase-Urteil zum Ziel (verzweigen Sie hierauf für Retry-Entscheidungen).->headers->original_status: HTTP-Status, den die Ziel-Site an Crawlbase zurückgegeben hat.->headers->storage_url/->headers->rid: gesetzt, wenn der Aufruf'store' => trueenthielt.