georanker / serp-sdk
PHP 8 SDK for the GeoRanker SERP API
Requires
- php: ^8.0
- ext-curl: *
- ext-json: *
This package is auto-updated.
Last update: 2026-05-13 11:45:09 UTC
README
A zero-dependency PHP 8 SDK for the GeoRanker SERP API. Create SERP requests, poll for results, and work with fully typed response objects.
Requirements
- PHP 8.0 or higher
ext-curlext-json
Installation
Via Composer
composer require georanker/serp-sdk
Without Composer
Clone or download the repository and include the autoloader:
require_once '/path/to/georanker-serp-sdk/autoload.php';
Quick Start
use GeoRanker\GeoRankerClient; use GeoRanker\Serp\SerpRequest; $client = new GeoRankerClient('your-api-key'); $pending = $client->addSerp(new SerpRequest( keyword: 'pizza delivery', region: 'New York,New York,United States', )); // Poll until the crawl finishes do { sleep(3); $serp = $client->getSerp($pending->id); } while (!$serp->ready); foreach ($serp->data->organic as $result) { echo $result->position . '. ' . $result->title . "\n"; echo ' ' . $result->url . "\n"; }
SSL on Windows / WAMP
Windows does not ship a CA certificate bundle for PHP. Download cacert.pem, save it locally, then pass the path to the client:
$client = new GeoRankerClient('your-api-key', 'C:\wampserver\cacert.pem');
Alternatively, set it globally in php.ini and restart your server — then no second argument is needed:
curl.cainfo = "C:\wampserver\cacert.pem" openssl.cafile = "C:\wampserver\cacert.pem"
Creating SERP Requests
Single request (asynchronous — default)
$pending = $client->addSerp(new SerpRequest( keyword: 'best coffee shops', searchEngine: 'google', region: 'London,England,United Kingdom', maxResults: 10, isMobile: false, language: 'en', )); echo $pending->id; // use this to fetch results later echo $pending->ready; // false — crawl not finished yet
Single request (synchronous — waits up to 300 s)
$serp = $client->addSerp(new SerpRequest( keyword: 'plumber near me', region: 'Chicago,Illinois,United States', priority: 'REALTIME', // doubles credit cost asynchronous: false, // block until crawl finishes )); var_dump($serp->data->organic);
Coordinate-based region targeting
use GeoRanker\Serp\RegionSearch; $serp = $client->addSerp(new SerpRequest( keyword: 'coffee shop', searchEngine: 'google', regionSearch: new RegionSearch( latitude: 48.8566, longitude: 2.3522, maxDistance: 5000, // metres (optional) types: ['city', 'municipality'], ), ));
Note: Do not set
regionwhen usingregionSearch.
Bulk create (up to 1 000)
$pendings = $client->addSerpList([ new SerpRequest('keyword one', region: 'Paris,France'), new SerpRequest('keyword two', region: 'Berlin,Germany'), new SerpRequest('keyword three', region: 'Tokyo,Japan'), ]); $ids = array_map(fn($r) => $r->id, $pendings);
Fetching Results
Single SERP by ID
$serp = $client->getSerp('5d16674bb45b3b17173b095b'); if ($serp->ready) { // access typed result sets }
Bulk fetch by IDs
$results = $client->getSerpList([ '5d16674bb45b3b17173b095b', '5d16674bb45b3b17173b095c', ]); foreach ($results as $serp) { echo $serp->id . ' ready: ' . ($serp->ready ? 'yes' : 'no') . "\n"; }
Working with Response Data
All response objects are fully typed. Once $serp->ready is true:
// Region that was used echo $serp->region->canonicalName; // "New York,New York,United States" echo $serp->region->countryCode; // "US" // Metadata echo $serp->data->totalResults; // 1940000000 echo $serp->keyword; echo $serp->searchEngine; echo $serp->createdAt; echo $serp->generatedAt; // Organic results foreach ($serp->data->organic as $result) { echo $result->position . '. ' . $result->title; echo ' URL: ' . $result->url; echo ' Domain: ' . $result->domain; echo ' Snippet: '. $result->text; } // Maps / local pack foreach ($serp->data->maps as $result) { echo $result->position . '. ' . $result->title; } // People Also Ask foreach ($serp->data->paa as $result) { echo $result->title; // the question echo $result->text; // the answer snippet } // Knowledge Graph foreach ($serp->data->knowledgeGraph as $result) { echo $result->title; echo $result->category; // e.g. "Dish" echo $result->imageUrl; } // Related searches foreach ($serp->data->related as $result) { echo $result->text; echo $result->url; } // AI results (raw array — schema varies by search engine) var_dump($serp->data->ai);
Search Engines
| Value | Engine | Result location |
|---|---|---|
google |
Google Web Search | data->organic, data->maps, data->paa, etc. |
googlelocal |
Google Maps | data->maps |
googleimages |
Google Images | data->organic |
google-aimode |
Google AI Mode | data->ai |
bing |
Bing | data->organic |
yahoo |
Yahoo | data->organic |
youtube |
YouTube | data->organic |
naver |
Naver | data->organic |
baidu |
Baidu | data->organic |
sogou |
Sogou | data->organic |
universal |
Raw crawl data for any URL | data->raw (array) |
chatgpt |
ChatGPT | data->ai (array) |
perplexity |
Perplexity | data->ai (array) |
Special Engines
Universal — crawl any URL
Pass the target URL as the keyword. The full raw HTML of the page is returned in $serp->data->raw.
$serp = $client->addSerp(new SerpRequest( keyword: 'https://www.georanker.com', searchEngine: 'universal', priority: 'INSTANT', region: 'US', asynchronous: false, )); $raw = $serp->data->raw; // array of raw crawl data
ChatGPT
Pass your prompt as the keyword. The AI answer is returned in $serp->data->ai.
$serp = $client->addSerp(new SerpRequest( keyword: 'What is GeoRanker?', searchEngine: 'chatgpt', priority: 'INSTANT', region: 'US', asynchronous: false, )); var_dump($serp->data->ai);
Perplexity
Same pattern as ChatGPT — prompt goes in keyword, answer comes back in $serp->data->ai.
$serp = $client->addSerp(new SerpRequest( keyword: 'What is GeoRanker?', searchEngine: 'perplexity', priority: 'INSTANT', region: 'US', asynchronous: false, )); var_dump($serp->data->ai);
Priority Levels
| Value | Behaviour | Cost multiplier |
|---|---|---|
LOW |
Async by default | 1× |
NORMAL |
Async by default | 1× |
REALTIME |
Sync by default | 2× |
INSTANT |
Sync by default | 5× |
Advanced Parameters
Custom URL parameters
Appended to every URL during the crawl. Useful for UULE location encoding or forcing locale.
new SerpRequest( keyword: 'pizza', region: 'New York,New York,United States', customUrlParameter: [ ['name' => 'uule', 'value' => 'w+CAIQICIgTmV3IFlvcmssVW5pdGVkIFN0YXRlcw=='], ['name' => 'hl', 'value' => 'en'], ['name' => 'pws', 'value' => null], // null removes the default parameter ], );
Custom cookies
new SerpRequest( keyword: 'pizza', region: 'London,England,United Kingdom', customCookieParameter: [ ['name' => 'CONSENT', 'value' => 'YES+'], ], );
Custom User-Agent
new SerpRequest( keyword: 'pizza', region: 'London,England,United Kingdom', customUserAgent: 'Mozilla/5.0 (compatible; MyBot/1.0)', saveRawData: true, // recommended when using a custom UA );
Callback URL
Called via POST when the SERP is ready. Receives id and type fields.
new SerpRequest( keyword: 'pizza', region: 'London,England,United Kingdom', callback: 'https://mysite.com/webhook.php', callbackFormat: 'JSON', // 'SIMPLE' or 'JSON' );
Error Handling
All exceptions extend GeoRanker\Exceptions\GeoRankerException.
use GeoRanker\Exceptions\AuthException; use GeoRanker\Exceptions\BadRequestException; use GeoRanker\Exceptions\CreditException; use GeoRanker\Exceptions\NotFoundException; use GeoRanker\Exceptions\RateLimitException; use GeoRanker\Exceptions\ServerException; use GeoRanker\Exceptions\GeoRankerException; try { $serp = $client->addSerp(new SerpRequest('pizza', region: 'London,England,United Kingdom')); } catch (AuthException $e) { // 403 — invalid API key } catch (BadRequestException $e) { // 400 — wrong region, invalid search engine, etc. } catch (CreditException $e) { // 402 — out of credits or rate limit exceeded } catch (NotFoundException $e) { // 404 — SERP ID not found or too old } catch (RateLimitException $e) { // 429 — too many concurrent requests } catch (ServerException $e) { // 500 / 502 / 504 — GeoRanker server error, retry later echo $e->getStatusCode(); } catch (GeoRankerException $e) { // any other API or cURL error echo $e->getStatusCode() . ': ' . $e->getMessage(); }
SerpRequest Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
keyword |
string |
— | Required. Exact keyword to search. |
searchEngine |
string |
google |
Search engine to use. |
region |
string|null |
null |
Canonical region name or country code. |
regionSearch |
RegionSearch|null |
null |
Coordinate-based region (omit region when used). |
priority |
string |
NORMAL |
LOW, NORMAL, REALTIME, or INSTANT. |
asynchronous |
bool|null |
null |
false = wait for result (up to 300 s). |
callback |
string|null |
null |
Webhook URL called when result is ready. |
callbackFormat |
string |
JSON |
SIMPLE or JSON. |
maxResults |
int|null |
null |
Number of organic results (min 10). |
isMobile |
bool |
false |
Use a mobile browser. |
language |
string |
en |
ISO 639-1 language code. |
saveRawData |
bool |
false |
Save raw HTML. Recommended with custom UA. |
customUserAgent |
string|null |
null |
Override the crawler User-Agent (≤ 250 chars). |
customUrlParameter |
array|null |
null |
[["name"=>…,"value"=>…]] appended to crawl URLs. |
customCookieParameter |
array|null |
null |
[["name"=>…,"value"=>…]] merged into cookie header. |
voiceSearchHighFidelity |
bool |
false |
High-fidelity voice transcription (Google only). |