How to Export SERP API Results to Google Sheets
Learn how to export SERP API results to Google Sheets using Python. Fetch search results, extract titles, links, snippets, rankings, and metadata, then append them to a spreadsheet.
Google Sheets is often the easiest place to review SERP data.
You may not need a full database on day one. If your team wants to check rankings, compare domains, review snippets, or share search results with SEO, product, or content teams, a spreadsheet is usually enough.
The workflow is simple:
SERP API request
→ Receive SERP JSON
→ Extract titles, links, snippets, positions, and metadata
→ Append rows to Google Sheets
This guide shows how to export SERP API results to Google Sheets with Python. The example is provider-neutral, so you can adapt it to Talordata, SerpApi, Serper.dev, Bright Data, SearchAPI, or any SERP API that returns structured JSON.
What SERP Data Should You Export?
For most workflows, start with organic search results. You do not need every field from the raw response.
A useful spreadsheet usually includes:
|
Column |
Meaning |
|---|---|
|
|
Search keyword |
|
|
Google, Bing, Yandex, DuckDuckGo, etc. |
|
|
Search country, region, or city |
|
|
Desktop or mobile |
|
|
Ranking position |
|
|
Result title |
|
|
Destination URL |
|
|
Extracted domain |
|
|
Search result summary |
|
|
Timestamp |
This structure works well for SEO rank tracking, competitor monitoring, brand visibility checks, and AI source discovery.
Step 1: Install Python Packages
You need three packages:
pip install requests gspread google-auth
requests calls the SERP API.gspread writes rows to Google Sheets.google-auth handles Google service account authentication.
Step 2: Prepare Google Sheets Access
Create a Google Sheet with a tab named SERP Results.
Then create a Google Cloud service account, download the JSON credentials file, and share your Google Sheet with the service account email.
Your project folder may look like this:
project/
export_serp_to_sheets.py
service_account.json
Do not commit service_account.json to GitHub or any public repository.
Step 3: Fetch SERP API Results
The exact SERP API endpoint depends on your provider. This example keeps the request generic.
import os
import requests
SERP_API_KEY = os.getenv("SERP_API_KEY")
SERP_API_ENDPOINT = os.getenv("SERP_API_ENDPOINT")
def fetch_serp_results(query, location="United States", device="desktop"):
params = {
"engine": "google",
"query": query,
"location": location,
"device": device,
"output": "json"
}
headers = {
"Authorization": f"Bearer {SERP_API_KEY}"
}
response = requests.get(
SERP_API_ENDPOINT,
params=params,
headers=headers,
timeout=30
)
response.raise_for_status()
return response.json()
You can use the same pattern with different providers. Some APIs use q instead of query, or pass the API key as a query parameter instead of an authorization header. Keep the parsing layer separate so provider changes do not affect your spreadsheet logic.
Step 4: Normalize SERP JSON
SERP APIs may use slightly different field names. One API may return link, another may use url. One may use snippet, another may use description.
A flexible parser avoids breaking when fields are missing.
from urllib.parse import urlparse
from datetime import datetime, timezone
def clean_text(value):
if not value:
return ""
return " ".join(str(value).split())
def get_domain(url):
if not url:
return ""
parsed = urlparse(url)
return parsed.netloc.replace("www.", "") if parsed.netloc else ""
def extract_organic_results(serp_json, query, location, device):
organic_results = serp_json.get("organic_results", [])
collected_at = datetime.now(timezone.utc).isoformat()
rows = []
for index, item in enumerate(organic_results, start=1):
link = item.get("link") or item.get("url")
if not link:
continue
rows.append([
query,
serp_json.get("search_parameters", {}).get("engine", "google"),
location,
device,
item.get("position") or index,
clean_text(item.get("title")),
link,
get_domain(link),
clean_text(item.get("snippet") or item.get("description")),
collected_at
])
return rows
This function returns rows in the same order as your spreadsheet columns.
Step 5: Append Rows to Google Sheets
Now connect to Google Sheets and append the rows.
import gspread
from google.oauth2.service_account import Credentials
GOOGLE_SHEET_NAME = "SERP API Results"
WORKSHEET_NAME = "SERP Results"
SERVICE_ACCOUNT_FILE = "service_account.json"
def get_worksheet():
scopes = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive"
]
credentials = Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE,
scopes=scopes
)
client = gspread.authorize(credentials)
spreadsheet = client.open(GOOGLE_SHEET_NAME)
return spreadsheet.worksheet(WORKSHEET_NAME)
def append_rows_to_sheet(rows):
if not rows:
print("No rows to append.")
return
worksheet = get_worksheet()
worksheet.append_rows(rows, value_input_option="RAW")
print(f"Appended {len(rows)} rows.")
Before appending data, add this header row to your sheet:
query | engine | location | device | position | title | link | domain | snippet | collected_at
Complete Script
Here is the full version:
import os
import requests
import gspread
from urllib.parse import urlparse
from datetime import datetime, timezone
from google.oauth2.service_account import Credentials
SERP_API_KEY = os.getenv("SERP_API_KEY")
SERP_API_ENDPOINT = os.getenv("SERP_API_ENDPOINT")
GOOGLE_SHEET_NAME = "SERP API Results"
WORKSHEET_NAME = "SERP Results"
SERVICE_ACCOUNT_FILE = "service_account.json"
def clean_text(value):
if not value:
return ""
return " ".join(str(value).split())
def get_domain(url):
if not url:
return ""
parsed = urlparse(url)
return parsed.netloc.replace("www.", "") if parsed.netloc else ""
def fetch_serp_results(query, location="United States", device="desktop"):
params = {
"engine": "google",
"query": query,
"location": location,
"device": device,
"output": "json"
}
headers = {
"Authorization": f"Bearer {SERP_API_KEY}"
}
response = requests.get(
SERP_API_ENDPOINT,
params=params,
headers=headers,
timeout=30
)
response.raise_for_status()
return response.json()
def extract_organic_results(serp_json, query, location, device):
organic_results = serp_json.get("organic_results", [])
collected_at = datetime.now(timezone.utc).isoformat()
rows = []
for index, item in enumerate(organic_results, start=1):
link = item.get("link") or item.get("url")
if not link:
continue
rows.append([
query,
serp_json.get("search_parameters", {}).get("engine", "google"),
location,
device,
item.get("position") or index,
clean_text(item.get("title")),
link,
get_domain(link),
clean_text(item.get("snippet") or item.get("description")),
collected_at
])
return rows
def get_worksheet():
scopes = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive"
]
credentials = Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE,
scopes=scopes
)
client = gspread.authorize(credentials)
spreadsheet = client.open(GOOGLE_SHEET_NAME)
return spreadsheet.worksheet(WORKSHEET_NAME)
def append_rows_to_sheet(rows):
if not rows:
print("No rows to append.")
return
worksheet = get_worksheet()
worksheet.append_rows(rows, value_input_option="RAW")
print(f"Appended {len(rows)} rows.")
if __name__ == "__main__":
query = "best project management software"
location = "United States"
device = "desktop"
serp_json = fetch_serp_results(query, location, device)
rows = extract_organic_results(serp_json, query, location, device)
append_rows_to_sheet(rows)
Where Talordata and Other SERP APIs Fit
This workflow works with any SERP API that returns structured JSON.
For quick Google-only prototypes, tools like Serper.dev or SerpApi may be easy to test. For larger data collection workflows, teams may compare Bright Data, SearchAPI, or DataForSEO.
Talordata is worth testing when you need structured SERP results, JSON / HTML output, geo-targeted searches, and support for multiple search engines such as Google, Bing, Yandex, and DuckDuckGo. That makes it useful when Google Sheets is only the first step before moving data into dashboards, AI agents, or monitoring systems. Start testing 1000 free API requests
The practical test is simple: run the same queries through two or three APIs, export the results to the same sheet, then compare field completeness, missing URLs, localization quality, and cost per usable row.
Common Use Cases
SEO Rank Tracking
Exporting SERP data to Google Sheets helps teams review ranking positions without building a dashboard first.
Competitor Monitoring
You can group results by domain and track which competitors appear for important keywords.
Content Research
Writers can review titles, snippets, and ranking URLs before planning new content.
AI Agent Source Discovery
AI agents can use spreadsheet rows as a lightweight source list before fetching full pages.
FAQ
Can I export SERP API results to Google Sheets automatically?
Yes. You can use Python to call a SERP API, parse the JSON response, and append rows to Google Sheets using the Google Sheets API or a library like gspread.
What SERP fields should I export?
Start with query, engine, location, device, position, title, link, domain, snippet, and timestamp. These fields work well for SEO, competitor monitoring, and AI source discovery.
Do I need a database?
Not always. Google Sheets is enough for testing, small reports, and team review. For large-scale monitoring, a database is usually better.