API Platform
SERP API
Retrieve Google search results in structured JSON or raw HTML format.
Retrieve Google search results in structured JSON or raw HTML format. Supports multi-page queries, mobile/desktop results, and localized searches by language and country.
Product page: SERP API.
Authentication
All requests require header-based authentication. Include your API credentials in every request.
| Header | Type | Description |
|---|---|---|
SEMUST-API-USER | string | Your API user's username |
SEMUST-API-PASSWORD | string | Your API user's password |
Create API credentials from the API Access page.
SEMUST-API-USER: your_username
SEMUST-API-PASSWORD: your_passwordRequest Parameters
Send a application/json body with the following parameters:
Body
keywordstringrequiredThe search query to look up on Google.
languagestringdefault: enLanguage code (ISO 639-1). Controls the language of search results. Examples: "en", "tr", "de", "fr", "es".
countrystringdefault: USCountry code (ISO 3166-1 alpha-2). Geo-targets search results to a specific country. Examples: "US", "TR", "DE", "GB".
formatstringdefault: jsonResponse format. "json" returns parsed structured data. "raw" returns the full HTML of the search results page.
mobilebooleandefault: falseWhen true, returns mobile search results instead of desktop.
start_pageintegerdefault: 1First page of results to fetch. Must be between 1 and 10.
end_pageintegerdefault: 1Last page of results to fetch. Must be between 1 and 10, and >= start_page.
Pagination:
Both start_page and end_page must be between 1 and 10. end_page must be >= start_page. Multi-page requests return an array.
{
"keyword": "best seo tools",
"language": "en",
"country": "US",
"format": "json",
"mobile": false,
"start_page": 1,
"end_page": 1
}Code Examples
Complete examples showing how to call the SERP API in different languages.
curl -X POST https://data.semust.com/v1/serp \
-H "Content-Type: application/json" \
-H "SEMUST-API-USER: your_username" \
-H "SEMUST-API-PASSWORD: your_password" \
-d '{
"keyword": "best seo tools",
"language": "en",
"country": "US",
"format": "json"
}'import requests
response = requests.post(
"https://data.semust.com/v1/serp",
headers={
"SEMUST-API-USER": "your_username",
"SEMUST-API-PASSWORD": "your_password",
},
json={
"keyword": "best seo tools",
"language": "en",
"country": "US",
"format": "json",
},
)
if response.status_code == 200:
data = response.json()
for result in data.get("organic", []):
print(f"{result['rank']}. {result['title']}")
print(f" URL: {result['link']}")
print(f" Source: {result.get('source', 'N/A')}")
else:
print(f"Error [{response.status_code}]: {response.text}")const response = await fetch("https://data.semust.com/v1/serp", {
method: "POST",
headers: {
"Content-Type": "application/json",
"SEMUST-API-USER": "your_username",
"SEMUST-API-PASSWORD": "your_password",
},
body: JSON.stringify({
keyword: "best seo tools",
language: "en",
country: "US",
format: "json",
}),
});
if (response.ok) {
const data = await response.json();
data.organic?.forEach((result) => {
console.log(`${result.rank}. ${result.title}`);
console.log(` URL: ${result.link}`);
console.log(` Source: ${result.source || "N/A"}`);
});
} else {
const text = await response.text();
console.error(`Error [${response.status}]: ${text}`);
}package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
payload := map[string]interface{}{
"keyword": "best seo tools",
"language": "en",
"country": "US",
"format": "json",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST",
"https://data.semust.com/v1/serp",
bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("SEMUST-API-USER", "your_username")
req.Header.Set("SEMUST-API-PASSWORD", "your_password")
resp, err := (&http.Client{}).Do(req)
if err != nil {
fmt.Printf("Request failed: %v\n", err)
return
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
if resp.StatusCode == 200 {
var data map[string]interface{}
json.Unmarshal(respBody, &data)
if organic, ok := data["organic"].([]interface{}); ok {
for _, item := range organic {
r := item.(map[string]interface{})
fmt.Printf("%v. %v\n", r["rank"], r["title"])
fmt.Printf(" URL: %v\n", r["link"])
fmt.Printf(" Source: %v\n", r["source"])
}
}
} else {
fmt.Printf("Error %d: %s\n",
resp.StatusCode, string(respBody))
}
}<?php
$payload = json_encode([
"keyword" => "best seo tools",
"language" => "en",
"country" => "US",
"format" => "json",
]);
$ch = curl_init("https://data.semust.com/v1/serp");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"SEMUST-API-USER: your_username",
"SEMUST-API-PASSWORD: your_password",
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
foreach ($data["organic"] ?? [] as $result) {
echo $result["rank"] . ". " . $result["title"] . "\n";
echo " URL: " . $result["link"] . "\n";
echo " Source: " . ($result["source"] ?? "N/A") . "\n";
}
} else {
echo "Error [{$httpCode}]: {$response}\n";
}Multi-Page Requests
To fetch multiple pages of search results, set start_page and end_page.
The response will be an array of result objects, one per page. Each object contains the same fields as a single-page response (organic, knowledge_graph, …).
Credits
Each page in a paginated request is charged at the base cost. For example, requesting 3 pages (start_page: 1, end_page: 3) will consume 3x the base credit cost.
import requests
response = requests.post(
"https://data.semust.com/v1/serp",
headers={
"SEMUST-API-USER": "your_username",
"SEMUST-API-PASSWORD": "your_password",
},
json={
"keyword": "best seo tools",
"format": "json",
"start_page": 1,
"end_page": 3,
},
)
pages = response.json()
for i, page in enumerate(pages, start=1):
print(f"--- Page {i} ---")
for result in page.get("organic", []):
print(f" {result['rank']}. {result['title']}")
print(f" URL: {result['link']}")
print(f" Source: {result.get('source', 'N/A')}")Response
JSON Format
Returns parsed search result data. Single-page requests return an object, multi-page requests return an array.
Internal metadata fields (general, url, pagination, input) are automatically removed.
Raw Format
Returns the raw HTML content of the search results page as text/html.
{
"organic": [
{
"rank": 1,
"global_rank": 1,
"title": "10 Best SEO Tools in 2025",
"description": "Discover the top SEO tools for improving your website rankings...",
"link": "https://example.com/best-seo-tools",
"display_link": "https://example.com › best-seo-tools",
"source": "Example.com",
"extensions": [
{
"type": "site_link",
"text": "Free Tools",
"link": "https://example.com/free-tools",
"rank": 1
}
]
},
{
"rank": 2,
"global_rank": 6,
"title": "SEO Software & Tools",
"description": "Get more search traffic with our comprehensive SEO toolkit...",
"link": "https://www.example.com",
"display_link": "https://www.example.com",
"source": "Example"
}
],
"knowledge": {
"name": "SEO",
"subtitle": "Search engine optimization",
"description": "Search engine optimization is the process of...",
"description_source": "Wikipedia",
"facts": [{ "key": "Full name", "value": [{ "text": "Search Engine Optimization" }] }]
},
"people_also_ask": [
{
"rank": 1,
"global_rank": 2,
"question": "What is SEO?",
"answer_source": "Wikipedia",
"answers": [{ "rank": 1, "type": "answer", "value": { "text": "SEO is..." } }]
}
],
"related": [
{ "rank": 1, "global_rank": 10, "text": "SEO tools free", "link": "https://..." }
],
"navigation": [{ "title": "Images", "href": "https://..." }],
"perspectives": [{ "title": "SEO Tips", "author": "Expert", "source": "YouTube" }],
"ai_overview": { "references": [...], "texts": [...] },
"images": [{ "rank": 1, "title": "SEO Diagram", "link": "https://...", "image": "https://..." }],
"top_ads": [{ "rank": 1, "title": "SEO Tool", "link": "https://...", "referral_link": "https://..." }],
"bottom_ads": [...]
}[
{
"organic": [
{ "rank": 1, "global_rank": 1, "title": "Result 1", "link": "https://...", "source": "..." }
],
"knowledge": { "name": "...", "description": "..." },
"people_also_ask": [{ "rank": 1, "question": "...", "answers": [...] }],
"navigation": [{ "title": "Images", "href": "https://..." }]
},
{
"organic": [
{ "rank": 1, "global_rank": 11, "title": "Page 2 Result", "link": "https://...", "source": "..." }
],
"related": [{ "rank": 1, "text": "Related search", "link": "https://..." }]
}
]Response Fields Reference
Root-Level Fields
The response contains multiple SERP elements. Not all fields are present in every response.
| Field | Type | Description |
|---|---|---|
organic | array | Main organic search results |
knowledge | object | Knowledge panel information (Wikipedia-like data) |
people_also_ask | array | "People also ask" questions with answers |
related | array | Related searches at bottom of SERP |
navigation | array | Search type tabs (Images, Videos, News, etc.) |
perspectives | array | Social media and forum perspectives |
ai_overview | object | AI-generated overview (Google AI Overviews) |
images | array | Image carousel results |
top_ads | array | Sponsored results at top of page |
bottom_ads | array | Sponsored results at bottom of page |
overview | object | Knowledge graph metadata (kgmid, title) |
Organic Result Fields
| Field | Type | Description |
|---|---|---|
rank | integer | Position within organic results (1-indexed) |
global_rank | integer | Position across all SERP elements |
title | string | Result title |
description | string | Result snippet/description |
link | string | Destination URL |
display_link | string | Formatted URL as displayed in SERP |
source | string | Website or source name |
extensions | array | Site links, dates, and other extensions |
image | string | Thumbnail URL (for video results) |
duration | string | Video duration (e.g., "19:10") |
duration_sec | integer | Video duration in seconds |
Error Codes
All errors return a JSON object with a human-readable message and an error code.
| HTTP | Code | Meaning |
|---|---|---|
| 400 | INVALID_REQUEST | Request body is malformed or missing required fields |
| 400 | KEYWORD_REQUIRED | The keyword field is empty or missing |
| 400 | INVALID_FORMAT | The format field is not "json" or "raw" |
| 401 | INVALID_API_KEY | Authentication failed — invalid username or password |
| 402 | INSUFFICIENT_CREDITS | Your account does not have enough credits |
| 429 | RATE_LIMIT_EXCEEDED | Too many requests — rate limit exceeded |
| 500 | INTERNAL_ERROR | An internal server error occurred |
| 502 | SERP_FAILED | Failed to fetch search results |
| 504 | TIMEOUT | The request timed out (max 10 minutes) |
{
"error": "Your account does not have enough credits",
"code": "INSUFFICIENT_CREDITS"
}Credits & Rate Limits
Credits
Each request consumes credits from your balance. Cost may vary based on the mobile parameter. If your balance is insufficient, the API returns HTTP 402.
Rate Limits
Requests are subject to per-minute and per-day limits based on your plan. Exceeding limits returns HTTP 429.
