The official Python SDK for the Scavio Search API. Access real-time data from 31 sources -- Google, Amazon, Walmart, eBay, Target, Home Depot, YouTube, Reddit, X, TikTok, TikTok Shop, Instagram, LinkedIn, Threads, Kuaishou, Zillow, Redfin, Booking.com, Tripadvisor, Airbnb, Yelp, Indeed, Glassdoor, the Apple App Store, Google Play, SEC EDGAR, Companies House, G2, Capterra, Google Ads Transparency and the Meta Ad Library -- plus extract() for reading any URL, all with a single API key. Built for AI agents, LLM applications, and data pipelines.
One API key, 31 data sources, 195 endpoints, structured JSON with knowledge graphs. A powerful alternative to Tavily, SerpAPI, and ScraperAPI for developers who need more than just web search.
| Feature | Scavio | Tavily | SerpAPI | ScraperAPI |
|---|---|---|---|---|
| Google Search | Yes | Yes | Yes | Yes |
| Amazon Products | Yes | No | Yes | No |
| Walmart Products | Yes | No | No | No |
| YouTube Search | Yes | No | Yes | No |
| Reddit Data (12 endpoints) | Yes | No | No | No |
| X Data (11 endpoints) | Yes | No | No | No |
| TikTok Data (11 endpoints) | Yes | No | No | No |
| TikTok Shop Data (8 endpoints) | Yes | No | No | No |
| Instagram Data (12 endpoints) | Yes | No | No | No |
| LinkedIn Data (9 endpoints) | Yes | No | No | No |
| eBay Sold-Listing Price History | Yes | No | No | No |
| Real Estate (Zillow + Redfin, 6 endpoints) | Yes | No | No | No |
| Travel (Booking + Airbnb + Tripadvisor, 10 endpoints) | Yes | No | No | No |
| Jobs & Employers (Indeed + Glassdoor, 8 endpoints) | Yes | No | No | No |
| Ad Transparency (Meta + Google, 6 endpoints) | Yes | No | No | No |
| Filings (SEC EDGAR + Companies House, 10 endpoints) | Yes | No | No | No |
Read Any URL (extract) |
Yes | Yes | No | Yes |
| Data Sources | 31 | 1 | 1 per plan | 1 |
| Structured JSON | Yes | Yes | Yes | Raw HTML |
| Knowledge Graphs | Yes | No | Yes | No |
| Async Client | Yes | Yes | No | No |
| Single API Key | Yes | Yes | No | No |
| Rate Limiting Built-in | Yes | No | No | No |
| Automatic Retries + Backoff | Yes | No | No | No |
| Fully Typed Parameters | Yes | No | No | No |
| Type Hints (PEP 561) | Yes | Yes | No | No |
Tavily focuses on AI-optimized web search. SerpAPI offers SERP parsing across search engines with separate plans. ScraperAPI provides raw web scraping with proxy rotation. Scavio combines multi-source structured data in a single search API for AI agents with one SDK and one API key.
pip install scavioGet your free API key at dashboard.scavio.dev.
from scavio import ScavioClient
client = ScavioClient(api_key="sk_...") # or set SCAVIO_API_KEY env var
results = client.search("best noise cancelling headphones 2026")
for r in results["organic_results"]:
print(r["title"], r["link"])Every method returns the API response as a plain dict. Amazon responses are
normalized to a stable, documented shape; the other endpoints pass the upstream
provider's shape through, so fields vary by endpoint.
Every endpoint exposes all of its parameters as explicit, documented,
autocomplete-friendly keyword arguments with Literal types for enums. Your
editor shows the full parameter set, allowed enum values, and defaults inline.
# Google web search with the full parameter surface
results = client.google.search(
"electric cars",
gl="us", # country of the search
hl="en", # UI language
location="Austin, Texas, United States",
time_period="last_month",
device="mobile",
)
# YouTube filters. The digit-named API fields (4k, 360, 3d) are exposed as
# valid Python identifiers: four_k, video_360, video_3d.
client.youtube.search("drone footage", four_k=True, hdr=True, duration="long")
# Amazon product lookup: pass the ASIN (sent to the API as `query`).
# `country` is the marketplace, as an ISO 3166-1 alpha-2 code.
client.amazon.product("B09XS7JWHH", country="gb")Any parameter the API adds in the future can be passed via **extra and is sent
verbatim, so you never have to wait for an SDK release:
client.google.search("openai", **{"some_new_param": "value"})The client automatically retries transient failures (HTTP 429 and 5xx, plus
network/timeout errors) with exponential backoff, jitter, and Retry-After
support. Configure or disable it with max_retries.
from scavio import ScavioClient
client = ScavioClient()
results = client.search("latest advances in quantum computing 2026")
context = "\n\n".join(
f"[{r['title']}]({r['link']})\n{r.get('snippet', '')}"
for r in results["organic_results"]
)
prompt = f"Based on these search results, summarize the latest advances:\n\n{context}"
# Pass `prompt` to your LLM of choice (OpenAI, Anthropic, etc.)
print(prompt[:500])from scavio import ScavioClient
client = ScavioClient()
query = "sony wh-1000xm5"
amazon = client.amazon.search(query, country="us")
walmart = client.walmart.search(query)
print("Amazon:")
for p in amazon["data"]["products"][:3]:
print(f" ${p['price']} - {p['title'][:60]}")
print("\nWalmart:")
for p in walmart["data"]["products"][:3]:
print(f" ${p['price']} - {p['title'][:60]}")from scavio import ScavioClient
client = ScavioClient()
data = client.amazon.product("B0BS1PRC4L")["data"]
print(f"Brand: {data['brand']}")
print(f"Title: {data['title']}")
print(f"Rating: {data['rating']} ({data['reviews_count']} reviews)")
print(f"Price: {data['price']} {data['currency']}")
# Same ASIN, every seller: price, condition, and who holds the buy box.
offers = client.amazon.offers("B0BS1PRC4L")["data"]
print(f"{offers['total_offers']} offers")
for o in offers["offers"][:5]:
tag = " (buy box)" if o["is_buy_box_winner"] else ""
print(f" {o['price']} {o['currency']} - {o['seller_name']} [{o['condition']}]{tag}")from scavio import ScavioClient
client = ScavioClient()
results = client.search("best project management software", gl="us")
for r in results["organic_results"]:
print(f"{r['position']}. {r['title']}")
print(f" {r['link']}")from scavio import ScavioClient
client = ScavioClient()
news = client.google.news("AI startups")
for article in news["news_results"][:5]:
print(f"[{article['source']}] {article['title']}")
print(f" {article['link']}")
print()from scavio import ScavioClient
client = ScavioClient()
videos = client.youtube.search("python tutorial", sort_by="view_count")
for v in videos["data"]["results"][:5]:
print(f"{v['title']} ({v['view_count']:,} views)")
print(f" {v['url']}")
# Full details for a specific video (metadata() is a deprecated alias of video())
video = client.youtube.video("dQw4w9WgXcQ")
print(f"\n{video['data']['title']}")
print(f" {video['data']['view_count']:,} views")
# Transcript, related videos, comments, channel, and streams
transcript = client.youtube.transcript("dQw4w9WgXcQ", format="text")
related = client.youtube.related("dQw4w9WgXcQ")
comments = client.youtube.comments("dQw4w9WgXcQ")
channel_id = client.youtube.channel_resolve("@mkbhd")["data"]["channel_id"]
channel = client.youtube.channel(channel_id)
streams = client.youtube.streams("dQw4w9WgXcQ")from scavio import ScavioClient
client = ScavioClient()
posts = client.reddit.search("best mechanical keyboard")
for post in posts["data"]["results"]:
print(f"r/{post['subreddit']} - {post['title']}")
print(f" {post['url']}")
print()
# Drill into a subreddit, a single post, or a redditor. reddit.post() takes a
# url or a post_id and returns the post alone -- comments are a separate call.
feed = client.reddit.subreddit_posts("MechanicalKeyboards", sort="TOP")
detail = client.reddit.post(post_id="t3_1v6ngaf")
comments = client.reddit.post_comments("t3_1v6ngaf", sort="TOP")
history = client.reddit.user_posts("spez")
popular = client.reddit.popular()
trending = client.reddit.trending()from scavio import ScavioClient
client = ScavioClient()
hashtag = client.tiktok.hashtag(hashtag_name="python")
info = hashtag["data"]["challengeInfo"]
print(f"#{info['challenge']['title']}")
print(f" Views: {int(info['statsV2']['viewCount']):,}")
print(f" Videos: {int(info['statsV2']['videoCount']):,}")from scavio import ScavioClient
client = ScavioClient()
profile = client.instagram.profile(username="instagram")
user = profile["data"]["user"]
print(f"@{user['username']} - {user['edge_followed_by']['count']:,} followers")
posts = client.instagram.user_posts(username="instagram", count=12)
reels = client.instagram.user_reels(username="instagram")
hashtags = client.instagram.search_hashtags("fashion")from scavio import ScavioClient
client = ScavioClient()
tweets = client.x.search("AI agents", search_type="Latest")
for t in tweets["data"]["timeline"][:5]:
print(f"@{t['screen_name']}: {t['text'][:80]}")
# Profile, a user's tweets, followers, and a single tweet's replies
profile = client.x.user("elonmusk")
timeline = client.x.user_tweets("elonmusk")
followers = client.x.user_followers("elonmusk")
replies = client.x.tweet_comments("1808168603721650364", rank="top")
trending = client.x.trending(country="UnitedStates")from scavio import ScavioClient
client = ScavioClient()
# Member profile (1 credit) and their recent posts (10 credits per page). A
# handle or a full LinkedIn URL works anywhere.
person = client.linkedin.person(username="williamhgates")
person_posts = client.linkedin.person_posts(url="https://www.linkedin.com/in/williamhgates/")
# Company profile and its recent posts
company = client.linkedin.company(company="microsoft")
company_posts = client.linkedin.company_posts(company="microsoft")
# Jobs: search, then pull full detail for one listing
job_results = client.linkedin.search_jobs("software engineer", location="United States")
job = client.linkedin.job(job_id=job_results["data"]["data"][0]["id"])
# A post and its comments (10 per page)
post = client.linkedin.post(post_id="7488618410256523265")
comments = client.linkedin.post_comments(post_id="7488618410256523265", page=1)Retired endpoints. The upstream provider withdrew the datasets behind
person_contact,company_people,company_jobs,search_peopleandsearch_posts. They remain callable but always return HTTP 410 and are never billed.company()still returnsfeatured_employees(a small sample of staff), andsearch_jobs()with a company name substitutes forcompany_jobs.
from scavio import ScavioClient
client = ScavioClient()
# Listings carry exact prices
results = client.tiktok_shop.search("phone case")
for p in results["data"]["products"][:5]:
print(p["title"], p["price"]["current"], p["shop"]["shop_name"])
# Detail adds description, variants, stock and shipping -- but NOT a price
# (upstream masks it), and it resolves only about 44% of the ids search returns.
# A 404 there is a normal outcome, not an error: skip the item, do not retry.
from scavio import NotFoundError
product_id = results["data"]["products"][0]["product_id"]
try:
detail = client.tiktok_shop.product(product_id)
print(detail["data"]["title"], len(detail["data"]["variants"]), "variants")
except NotFoundError:
pass # no detail data upstream for this product; skip it, do not retry
reviews = client.tiktok_shop.product_reviews(product_id, page_size=200, sort="relevant")
catalog = client.tiktok_shop.shop_products("7495514739648989419") # exact prices
tree = client.tiktok_shop.categories()
resolved = client.tiktok_shop.resolve("https://vt.tiktok.com/ZT2AHoGsE/")from scavio import ScavioClient
client = ScavioClient()
brand = "scavio"
reddit = client.reddit.search(brand)
tiktok = client.tiktok.search_videos(brand, count=5)
print(f"Reddit mentions ({len(reddit['data']['results'])}):")
for post in reddit["data"]["results"][:3]:
print(f" r/{post['subreddit']}: {post['title']}")
tiktok_videos = tiktok["data"].get("search_item_list", [])
print(f"\nTikTok mentions ({len(tiktok_videos)}):")
for v in tiktok_videos[:3]:
desc = v["aweme_info"].get("desc", "No description")
print(f" {desc[:80]}")from scavio import ScavioClient
client = ScavioClient()
product = client.walmart.product("123456789")
price = product["data"]["price"]
title = product["data"]["title"]
threshold = 50.00
if price and price < threshold:
print(f"PRICE DROP: {title[:60]}")
print(f" Now ${price} (threshold: ${threshold})")
else:
print(f"{title[:60]}: ${price}")import asyncio
from scavio import AsyncScavioClient
async def main():
async with AsyncScavioClient() as client:
google = await client.search("mechanical keyboard")
amazon = await client.amazon.search("mechanical keyboard", country="us")
print(f"Google: {len(google['organic_results'])} results")
print(f"Amazon: {len(amazon['data']['products'])} products")
for r in google["organic_results"][:3]:
print(f" Web: {r['title'][:60]}")
for p in amazon["data"]["products"][:3]:
print(f" Amazon: ${p['price']} - {p['title'][:50]}")
asyncio.run(main())from scavio import ScavioClient
client = ScavioClient()
usage = client.get_usage()
print(f"Plan: {usage['plan']}")
print(f"Credits remaining: {usage['credit_balance']}")extract is a core capability, not a platform, so it is a top-level method:
client.extract(url), never client.extract.extract(). It is the "read this
page" primitive an agent reaches for when the page is not on a site Scavio has
a dedicated namespace for.
from scavio import ScavioClient
client = ScavioClient()
# Default: readability Markdown, plain datacenter fetch. 1 credit.
page = client.extract("https://example.com/blog/post")["data"]
print(page["content_length"], "chars of", page["format"])
print(page["content"][:500])
# format="html" is the raw page; format="text" is the Markdown flattened.
raw = client.extract("https://example.com/blog/post", format="html")
# mode is the price-bearing parameter, and the only knob that matters on a
# hard target: "normal" (1 credit) -> "advanced", a full browser render
# (1 credit) -> "ultra", the hardest-target tier (2 credits).
hard = client.extract("https://example.com/spa", format="markdown", mode="ultra")
# Billing is charged only on a successful extraction: a dead link, a bot wall
# or a timeout costs nothing, so retrying up a tier is safe.Live listings tell you what sellers want. sold=True searches completed
listings that actually sold, which is what a pricing model needs.
from scavio import ScavioClient
client = ScavioClient()
sold = client.ebay.search(
query="airpods pro 2",
sold=True,
condition="used",
per_page=240, # 60, 120 or 240 only; anything else falls back to 60
min_price=50, # prices are numbers, so 49.99 is legal too
)["data"]
prices = sorted(p["price"] for p in sold["products"] if p.get("price"))
print("median sold price:", prices[len(prices) // 2])
# On the sold view eBay publishes no headline count, so total_results is null.
# Page with `page` until a page comes back empty rather than trusting a total.
assert sold["total_results"] is None
# On the LIVE view total_results is eBay's own estimate and an unstable one --
# four identical requests minutes apart reported 28k, 140k, 170k and 27k.
# Treat it as an order of magnitude, never as a count.
# `seller` works with no query at all, which is how you page a whole catalogue.
# ebay.seller() is a profile card only -- it cannot enumerate inventory.
catalogue = client.ebay.search(seller="mytechstore", page=1)["data"]
profile = client.ebay.seller("mytechstore")["data"]Meta pages the ad library by cursor, and the first page is a different size from the rest: 30 ads on page 1, then 10 per cursor page.
from scavio import ScavioClient
client = ScavioClient()
ads, cursor = [], None
while True:
# page_id is the advertiser's numeric Facebook Page id, as a string.
page = client.meta_ads.advertiser("20531316728", cursor=cursor)["data"]
ads.extend(page["ads"])
if not page["has_next_page"]:
break
cursor = page["next_cursor"]
print(len(ads), "ads")
# Every page is 1 credit, and past the first 30 ads a page is 10 ads, so a deep
# walk costs roughly one credit per ten ads. Budget for depth.
# Keyword search pages the same way. total_results caps at 50000 with
# total_is_capped true, because Meta itself only reports ">50,000" -- never
# present it as an exact count.
first = client.meta_ads.search(
"black friday", country="US", active_status="active"
)["data"]
if first["total_is_capped"]:
print("more than", first["total_results"], "ads match")
# Spend, reach, impressions and the paid-for-by disclosure are political-only.
# On commercial ads they are null by design, not a bug.
political = client.meta_ads.search("vote", ad_type="political_and_issue_ads")["data"]
# The cursor is a self-contained blob: every other filter is ignored while it
# is set, so do not "change the filter and keep paging" -- start a new walk.from scavio import (
ScavioClient,
InvalidAPIKeyError,
RateLimitError,
InsufficientCreditsError,
NotFoundError,
BadRequestError,
ScavioConnectionError,
ScavioTimeoutError,
ScavioAPIError,
ScavioError,
)
client = ScavioClient(api_key="sk_...")
try:
results = client.search("query")
except InvalidAPIKeyError:
print("Check your API key")
except RateLimitError:
print("Too many requests - upgrade your plan")
except InsufficientCreditsError:
print("Out of credits - purchase more at dashboard.scavio.dev")
except ScavioAPIError as e:
# Any other non-2xx response; inspect the details:
print(e.status_code, e.response_body)All exceptions inherit from ScavioError. HTTP errors (BadRequestError 400,
InvalidAPIKeyError 401, InsufficientCreditsError 402, NotFoundError 404,
RateLimitError 429, ScavioAPIError for anything else) carry .status_code
and .response_body. Network failures raise ScavioConnectionError /
ScavioTimeoutError after retries are exhausted.
client = ScavioClient(
api_key="sk_...",
base_url="https://api.scavio.dev", # custom base URL
timeout=30.0, # request timeout in seconds
max_requests_per_second=1, # client-side rate limit (1-10)
max_retries=2, # retries on 429/5xx/network (0 disables)
)The async client mirrors the sync one method-for-method. It keeps a single
pooled httpx.AsyncClient alive for its lifetime; close it with
await client.aclose() or use the async context manager.
import asyncio
from scavio import AsyncScavioClient
async def main():
async with AsyncScavioClient(api_key="sk_...") as client:
return await client.google.search("openai", gl="us")
asyncio.run(main())Scavio works with popular AI/LLM frameworks:
- LangChain --
pip install langchain-scavio - MCP Server -- for Claude, Cursor, and other MCP clients
- n8n -- no-code workflow automation
| Service | Endpoints | Credits |
|---|---|---|
search, ai_mode, maps_search, maps_place, maps_reviews, shopping, shopping_product, shopping_stores, flights, hotels, hotels_detail, news, trends, trending |
1 each | |
| Amazon | search, product, offers, options |
1 each (options free) |
| Walmart | search, product, reviews, category, offers, seller, seller_products |
1, except search/category on domain="com.mx", which cost 2 |
| YouTube | search, shorts, suggestions, video, metadata (deprecated alias of video), comments, comment_replies, transcript, related, channel_search, channel, channel_videos, channel_shorts, channel_community, channel_resolve, streams |
search/shorts 2, transcript 8, streams 3, rest 1 each |
search, search_suggestions, post, post_comments, comment_replies, subreddit, subreddit_posts, user, user_posts, user_comments, popular, trending |
1 each | |
| X | search, tweet, tweet_comments, tweet_retweeters, user, user_tweets, user_replies, user_media, user_followers, user_followings, trending |
1 each |
| TikTok | profile, user_posts, video, video_comments, comment_replies, search_videos, search_users, hashtag, hashtag_videos, user_followers, user_followings |
1 each |
| TikTok Shop | search, search_suggestions, product, product_reviews, categories, category_products, shop_products, resolve |
1 each |
profile, user_posts, user_reels, user_tagged, user_stories, post, post_comments, comment_replies, search_users, search_hashtags, user_followers, user_followings |
user_posts 2, post/comment_replies 8, the other nine 10 each |
|
person, person_about, person_posts, person_contact, company, company_posts, company_people, company_jobs, search_people, search_jobs, search_posts, job, post, post_comments |
job 30, person_posts/company_posts/search_jobs/post_comments 10 each, person/person_about/company/post 1 each; the five retired endpoints (person_contact, company_people, company_jobs, search_people, search_posts) return 410 and are never billed |
|
| Threads | profile, user_posts, user_replies, post, post_comments, search_users |
2, but profile/user_posts/user_replies cost 4 when addressed by username instead of user_id |
| Kuaishou | profile, user_posts, user_live, user_resolve, video, video_comments, comment_replies, videos_batch, search, search_videos, search_users, search_live, tag_feed, trending |
priced per endpoint: videos_batch 40, profile and the four search* 10 each, video 2, the rest 1 |
| eBay | search (live or sold listings), product, seller |
1 each |
| Target | search, category, product, reviews |
1 each |
| Home Depot | search, product, reviews |
2 each |
| Zillow | search, property, agent_reviews |
1 each |
| Redfin | search, property, market |
1 each |
| Booking.com | search, hotel, reviews |
1 each |
| Tripadvisor | locations (start here), search, location, reviews |
2 each |
| Airbnb | search, listing, reviews |
1 each |
| Yelp | search, business, reviews |
2 each |
| Indeed | search, job, company, company_reviews |
2 each |
| Glassdoor | companies (start here), company, reviews, salaries |
1 each |
| Apple App Store | search, app, reviews |
1 each |
| Google Play | search, app, reviews |
2 each |
| SEC EDGAR | lookup (start here), company, filings, concept, facts, search |
1 each |
| Companies House | search (start here), company, officers, filing_history |
1 each |
| G2 | search, product, reviews |
5 each |
| Capterra | search, product, reviews |
2 each |
| Google Ads Transparency | advertisers (start here), search, creative |
1 each |
| Meta Ad Library | search, advertiser, ad |
1 each |
| Extract (core, not a namespace) | client.extract(url) |
1 for mode="normal" or "advanced", 2 for "ultra"; only a successful extraction is billed |
Every method's full parameter list is available inline in your editor (typed keyword arguments with docstrings). See the API docs for field-level details.
- 21 new namespaces with 85 endpoints: Threads, Kuaishou, eBay, Target,
Home Depot, Zillow, Redfin, Booking.com, Tripadvisor, Airbnb, Yelp, Indeed,
Glassdoor, Apple App Store, Google Play, SEC EDGAR, Companies House, G2,
Capterra, Google Ads Transparency and the Meta Ad Library. With the Walmart
rebuild and
extractbelow, that is 93 endpoints in this batch and 195 in the SDK. Every method is typed and documented inline, on both the sync and async clients. client.extract(url, format=..., mode=...)is new, and is a top-level method, not a namespace. Reading an arbitrary URL is a core capability rather than a platform, so it isclient.extract(...), neverclient.extract.extract(...).- Walmart grew from 2 endpoints to 7 (
reviews,category,offers,seller,seller_productsare new) andsearch/productchanged shape.device,delivery_zipandstore_idare retired: the API answers 200 with a top-levelwarningsarray if you send them through**extra.domain(com|ca|com.mx) is new onsearchandcategory, and it is the price-bearing parameter.pagesupersedesstart_page, which stays as a deprecated alias. - Walmart
min_price/max_pricewidened frominttofloat. The backend was alwaysz.number(), so19.99was always accepted; the old annotation was simply wrong. No runtime behaviour changed. - Four surfaces are body-priced and their docstrings say so instead of
quoting a flat price: Walmart (
com.mxcosts 2), Threads (4 credits when addressed byusernameinstead ofuser_id), Kuaishou (1, 2, 10 or 40 per endpoint) andextract(mode="ultra"costs 2). - Some caveats worth knowing before you write a loop: eBay
sold=Truereturnstotal_results: null; Meta Ad Library pages are 30 ads then 10, and the cursor ignores every other filter; Capterrasearchdoes not paginate at all; Apple App Storesearchhas no pagination either (raiselimit, up to 200); Airbnb prices exist only onsearch, never onlisting.
reddit.post()now takespost_idas well asurl-- pass either one.urlstays the first positional argument, so existing calls are unaffected. The response is a flat post object and carries no comments; usereddit.post_comments()for those.youtube.shorts(sort_by=...)is now typed asrelevance | date | view_count | ratinginstead of a free-form string.youtube.search()lost itslocationflag. It was never part of the backend schema, so it was silently dropped rather than filtering anything.
Amazon moved to a new upstream and the API now returns a normalized shape instead of the previous raw provider payload.
searchreturns{query, page, total_results, total_results_text, count, products[], filters[], related_searches[]}. Each product is{asin, title, url, image, price, currency, rating, reviews_count, is_sponsored, position, badge, sales_volume, delivery{is_free, date, fastest_date}}.productreturns flat fields:price,list_price,currency,rating,reviews_count,features,images,videos,variants,specifications,best_sellers_rank,shipping, and more. The oldbuybox[]array no longer exists -- useoffersfor per-seller pricing.offersis new: every seller for one ASIN, withprice,condition,seller_name,is_buy_box_winner,is_fulfilled_by_amazon, and delivery windows.country(ISO 3166-1 alpha-2:us,gb,de) is the marketplace selector and replacesdomain.pagereplacesstart_page. The old names still work as deprecated aliases.- Nine parameters were removed:
language,currency,device,sort_by,pages,category_id,merchant_id,zip_code,autoselect_variant.sort_byin particular was verified to be ignored by the marketplace, so result sorting is not available at any layer. Sending one of them anyway (via**extra) still returns 200, with a top-levelwarningsarray explaining what was ignored. optionsstill returnsdomainsandcountries;languagesandcurrenciesare now always empty, because neither is a request parameter any more.
MIT
Scavio is a unified search API built for AI agents — one API key, structured JSON, no scraping or proxies. A real-time Tavily alternative and SerpAPI alternative with data from:
- Google Search API — SERP results, news, images, maps, and knowledge graph
- Amazon Product API and Walmart Product API — product search and details
- YouTube API, TikTok API, and Instagram API — video and social media data
- TikTok Shop API — product search, detail, reviews, categories, and shop catalogs
- Reddit API — posts, comments, subreddits, and trending
- X API and LinkedIn API — tweets, profiles, companies, and jobs
For a detailed head-to-head breakdown, see Tavily vs Scavio.
Get a free API key and explore the documentation.