Integrate search data into your AI workflow, RAG / fine-tuning, or Python application using this official SerpApi Python SDK.
SerpApi supports Google, Google Maps, Google Shopping, Baidu, Yandex, Yahoo, eBay, App Stores, and more.
Python 3.6 or later is required.
To install the serpapi package, simply run the following command inside your Python virtual environment:
pip install serpapiPlease note that this package is separate from the legacy
serpapimodule, which is available on PyPi asgoogle-search-results. This package is maintained by SerpApi, and is the recommended way to access the SerpApi service from Python.
Create a SerpApi account to get your API key, then store it in an environment variable:
export SERPAPI_KEY="your_api_key"Environment variables keep secrets out of your source code.
Python accesses these variables from os.getenv("SERPAPI_KEY").
Run a Google search and access the results as a Python dict:
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "google",
"q": "coffee"
})
pprint(results)The results variable now contains a SerpResults object, which acts just like a dict, with some convenient functions added on top.
This example runs a search for "coffee" on Google. See the playground to generate your own code.
Unsuccessful requests raise serpapi.HTTPError or serpapi.TimeoutError exceptions. The returned status code will reflect the sort of error that occurred, please refer to Status and Error Codes Documentation for more details.
import os
import serpapi
# A default timeout can be set here.
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"), timeout=10)
try:
results = client.search({
"engine": "google",
"q": "coffee",
})
except serpapi.HTTPError as e:
if e.status_code == 401: # Invalid API key
print(e.error) # "Invalid API key. Your API key should be here: https://serpapi.com/manage-api-key"
elif e.status_code == 400: # Missing required parameter
pass
elif e.status_code == 429: # Exceeds the hourly throughput limit OR the account has run out of searches
pass
except serpapi.TimeoutError as e:
# Handle timeout
print(f"The request timed out: {e}")- Asynchronous searches for submitting non-blocking jobs and retrieving completed results from the Search Archive API.
- Persistent connections and connection pooling for reusing HTTP connections across searches.
- Search results as Python dict with
search, token-efficient Markdown withmd, or raw search-engine HTML withhtml. - SDK methods for the Image API, Location API, Search Archive API, and Account API.
- Configurable HTTP timeouts established by setting
timeoutin the client.
Use search and default output (none) for structured results decoded into a dict:
results = client.search({
"engine": "google",
"q": "coffee"
})Use md output for a token-efficient Markdown string optimized for LLMs and AI agents:
markdown = client.search({
"engine": "google",
"q": "coffee",
"output": "md"
})Use html output when you need the raw search-engine response:
raw_html = client.search({
"engine": "google",
"q": "coffee",
"output": "html"
})Archived results are also available as Markdown with
client.search_archive(search_id=search_id, output="md").
Learn more about SerpApi Markdown output.
The client is configured with your API key (and an optional timeout parameter) when you create it:
import os
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))| Option | Default | Description |
|---|---|---|
api_key |
None |
Your SerpApi API key. Use an environment variable rather than committing it to source control. |
timeout |
None |
Timeout in seconds for each HTTP request. By default no timeout is set, so a request can wait indefinitely. |
Everything else is passed with each call:
The client has no default engine or async setting, so include them in every search.
Use {"async": True} to submit searches without waiting for them to complete.
- Non-blocking (
{"async": True}): a single process can submit many searches and collect the results later from the Search Archive API. The code is more complex because you have to track search IDs and check their status. - Blocking (
{"async": False}, the default): each call waits for its results before returning, which keeps the code simple.
Note:
asyncis a reserved keyword in Python 3.7+, so pass it inside the parameters dictionary ({"async": True}) rather than as a keyword argument.
Here is an example of asynchronous searches using Python:
import os
import re
import time
from queue import Queue
import serpapi
company_list = ["meta", "amazon", "apple", "netflix", "google"]
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
schedule_search = Queue()
result = None
for company in company_list:
result = client.search({"engine": "google", "q": company, "async": True})
if re.search(r"Cached", result["search_metadata"]["status"]):
print(f"{company}: search results found in cache for: {company}")
schedule_search.put(result["search_metadata"]["id"])
print(f"Last search submitted at: {result['search_metadata']['created_at']}")
print("wait 10s for all requests to be completed")
time.sleep(10)
print("wait until all searches are cached or success")
while not schedule_search.empty():
search_id = schedule_search.get()
search_archived = client.search_archive(search_id=search_id)
company = search_archived["search_parameters"]["q"]
status = search_archived["search_metadata"]["status"]
if re.search(r"Cached|Success", status):
print(f"{company}: search results found in archive for: {company}")
continue
if status == "Error":
print(f"{company}: search failed: {search_archived.get('error')}")
continue
schedule_search.put(search_id)
time.sleep(1)
print("done")This code batches searches into a queue. Each search can take a few seconds to complete, so by the time the first ID is popped, its results are usually already in the archive. Searches that are still processing are put back in the queue and checked again.
Here are some examples of our most popular APIs. You can find the full list of supported engines and parameters in our documentation.
Scrape Google Shopping results with product names, prices, ratings, and merchant information.
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "google_shopping",
"q": "Macbook M4"
})
shopping_results = results["shopping_results"]
pprint(shopping_results)Google Shopping Light
A light variant engine called google_shopping_light is also available for faster, lower-cost shopping searches.
Scrape Google Images search results, including image URLs, thumbnails, titles, and source pages.
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "google_images",
"q": "coffee",
})
pprint(results)Google Images Light
A light variant engine called google_images_light is also available for faster, lower-cost image searches.
Google Lens accepts either a publicly accessible image URL or an uploaded image. To search by URL, pass the URL directly:
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "google_lens",
"url": "https://i.imgur.com/HBrB8p0.png",
})
pprint(results)To search a local image, place a file named image.png in your working directory, upload it, and pass its temporary image_id to Google Lens:
upload = client.upload_image("image.png")
results = client.search({
"engine": "google_lens",
"image_id": upload["image_id"],
})Uploaded images can be JPG/JPEG, PNG, or WebP files up to 500 KB. The returned
image_id expires after 10 minutes.
See Image API documentation · See Google Lens image upload documentation
Track search interest over time and compare the popularity of search terms.
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "google_trends",
"q": "coffee",
"data_type": "TIMESERIES"
})
interest_over_time = results["interest_over_time"]
pprint(interest_over_time)Search flight routes, schedules, prices, and booking options.
Note: The
google_flightsengine does not useq. Specify route and date parameters such asdeparture_id,arrival_id,outbound_date, andreturn_date.
import os
from datetime import date, timedelta
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
outbounding = date.today()
returning = outbounding + timedelta(weeks=2)
results = client.search({
"engine": "google_flights",
"departure_id": "LAX",
"arrival_id": "AUS",
"outbound_date": outbounding,
"return_date": returning
})
best_flights = results["best_flights"]
pprint(best_flights)The Google AI Mode API returns AI-generated answers with structured text blocks, references, images, products, and more.
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "google_ai_mode",
"q": "best coffee maker"
})
text_blocks = results["text_blocks"]
pprint(text_blocks)Scrape Bing web search results, including organic results, ads, related searches, and more.
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "bing",
"q": "coffee"
})
pprint(results)Scrape DuckDuckGo search results, including organic results, ads, knowledge graphs, and related searches.
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "duckduckgo",
"q": "coffee",
})
pprint(results)Scrape Baidu search results, including organic results, answer boxes, and related searches.
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "baidu",
"q": "coffee",
})
pprint(results)Scrape Amazon product search results, including product names, prices, ratings, reviews, and availability.
Note: The
amazonengine uses thekparameter for a keyword search, notq.
import os
from pprint import pprint
import serpapi
client = serpapi.Client(api_key=os.getenv("SERPAPI_KEY"))
results = client.search({
"engine": "amazon",
"k": "Coffee",
"amazon_domain": "amazon.com"
})
organic_results = results["organic_results"]
pprint(organic_results)Documentation is available on Read the Docs.
Change history is available on GitHub.
MIT License.
Contributions are welcome. Make sure to read our contributing guide.
© 2026 SerpApi
