以 AI 机器人身份加入视频会议,提供语音、虚拟形象与屏幕共享四种模式。
浏览器
Airbnb Scraper API - Stay Search, Listing Detail, Reviews
试用Search Airbnb stays with the full discount ledger, pull one listing with its complete amenity list and rating breakdown, and page through real review bodies. 3 endpoints, 1 credit each, structured JSON.
它能做什么
Search Airbnb stays for a location and date window, read one listing in full, and page through its review bodies. All endpoints return structured JSON.
技能文档
Airbnb via Scavio
Search Airbnb stays for a location and date window, read one listing in full, and page through its review bodies. All endpoints return structured JSON.
When to trigger
Use this skill when the user asks to:
- Find Airbnb stays in a place for specific dates, with price, rating and capacity filters
- Compare nightly and stay-total prices across listings, including the discount ledger
- Pull one listing in full - description, capacity, the complete grouped amenity list, host profile, house rules, cancellation policy, photo tour
- Read the rating breakdown - six category ratings and the five-bucket star distribution
- Read actual guest review bodies with per-review ratings and dates
- Build short-term-rental market research, comp sets or host analytics
Setup
Get a free API key at scavio.dev (50 free credits to get started, no card required):
export SCAVIO_API_KEY=sk_live_your_key
Every request is a POST with a JSON body and:
Authorization: Bearer $SCAVIO_API_KEY
Endpoints
Base URL: https://api.scavio.dev. Every Airbnb endpoint costs 1 credit.
| Endpoint | Credits | What it returns |
|---|---|---|
POST /api/v1/airbnb/search | 1 | Stays: stay-total and per-night price with the full discount ledger, rating and review count, bedrooms/beds/baths, coordinates, badges, images, dates_are_defaulted |
POST /api/v1/airbnb/listing | 1 | One listing in full: description, property and room type, capacity and room counts, the complete grouped amenity list (including what the place does not have), host profile and stats, house rules with parsed check-in/out times, cancellation policy, sleeping arrangements, photo tour, every image, and the rating breakdown. No nightly price |
POST /api/v1/airbnb/reviews | 1 | Review bodies with per-review rating, date, and reviewer name/photo/location |
Two facts that decide how you call this
Prices are search-only. The room page carries no nightly rate under any parameters - with or without dates, and even under a rendered fetch. If the user wants a price for a specific listing, you must find it in a /search response. /listing will never have one.
The rating breakdown is listing-only. The six category ratings, the five-bucket star distribution and the synthesised review tags are server-rendered on /listing - they are not on /reviews. /reviews gives you the review text.
Workflow
- Search: call
/airbnb/searchwithlocationand, ideally,check_in+check_out. Readlistings[].listing_idandlistings[].price. - One listing: call
/airbnb/listingwith thatlisting_idor a full/rooms/URL. Query parameters on a pasted URL are discarded - they carry somebody else's dates. - Reviews: call
/airbnb/reviewswith the samelisting_id, sending an explicitlimitand steppingoffset.
Dates and currency
check_in and check_out must be sent together. A dateless search defaults to roughly +30 days for 5 nights - and Airbnb A/B tests both the window and the prices on that shape: the same URL has come back split across two different windows with first-row prices of $680, $802 and $2,238. The response flags this as dates_are_defaulted. If it is true, do not quote the price as an answer to a dated question.
currency defaults to USD in the transport. Send one explicitly; without it Airbnb prices off the proxy exit and two identical requests disagree.
Pagination
/searchis 18 listings per page and offers two mutually exclusive controls: a 1-basedpage, or the opaquenext_cursorfrom a previous response passed back ascursor.cursorwins overpage, so sending both is rejected. Pick one.page_countis on the response./reviewspages withlimit(1-50, default 30) andoffset(default 0).countis the listing's total review count;returnedis how many this page holds./listingtakes no paging parameter.
The limit / offset names are load-bearing. The underscored _limit / _offset used elsewhere in Airbnb's API are silently ignored here and pin the response at a fixed 7 rows for every offset - which reads as a paging loop that never advances.
Parameters
Search (/search)
| Parameter | Type | Default | Description |
|---|---|---|---|
location | string | required | City, region, ZIP, or a pasted airbnb.com/s/ URL (1-200 chars). Unresolvable is a 404 |
check_in / check_out | string | +30d / +5 nights | YYYY-MM-DD, sent together and in order |
adults | integer | -- | Adult guests |
children | integer | -- | Ages 2-12 |
infants | integer | -- | Infants |
pets | integer | -- | Pets |
min_price / max_price | number | -- | Whole-stay total, not per night |
room_type | string | -- | entire_home, private_room, shared_room, hotel_room |
min_bedrooms / min_beds / min_bathrooms | integer | -- | Minimum counts |
superhost | boolean | -- | Superhost listings only |
instant_book | boolean | -- | Instant Book only |
guest_favorite | boolean | -- | Guest Favourite only |
free_cancellation | boolean | -- | Free cancellation only |
amenities | string | -- | Comma-separated: wifi, air_conditioning, pool, kitchen, free_parking, washer, self_check_in, tv - or raw numeric Airbnb amenity ids |
currency | string | USD | ISO 4217 |
page | integer | -- | 1-based, 18 listings per page. Cannot be combined with cursor |
cursor | string | -- | next_cursor from a previous response. Wins over page |
room_type and the named amenities are validated before the scrape, on purpose: an unrecognised value makes Airbnb return the unfiltered set under a 200, so the user would pay for a filter that never ran.
Listing (/listing)
| Parameter | Type | Default | Description |
|---|---|---|---|
listing_id | string | required | Listing id or full /rooms/ URL; query params discarded |
check_in / check_out | string | -- | YYYY-MM-DD, sent together and in order |
adults / children / infants / pets | integer | -- | Party composition |
currency | string | USD | ISO 4217 |
Reviews (/reviews)
| Parameter | Type | Default | Description |
|---|---|---|---|
listing_id | string | required | Listing id or full /rooms/ URL |
limit | integer | 30 | 1-50. Send it explicitly - see the paging note |
offset | integer | 0 | Row offset |
currency | string | USD | ISO 4217 |
Examples
import requests
BASE = "https://api.scavio.dev"
# Your key from https://scavio.dev. Load it from your environment or secret
# store in real code - keep it out of source control.
API_KEY = "sk_your_key_here"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
# 1. Search a real date window - min_price/max_price are the WHOLE-STAY total
found = requests.post(f"{BASE}/api/v1/airbnb/search", headers=HEADERS,
json={"location": "Austin, TX", "check_in": "2026-09-08", "check_out": "2026-09-13",
"adults": 2, "max_price": 1500, "room_type": "entire_home",
"amenities": "wifi,pool", "currency": "USD"}).json()
assert found["data"]["dates_are_defaulted"] is False # you sent dates, so this is False
row = found["data"]["listings"][0]
listing_id, stay_price = row["listing_id"], row["price"]
# 2. Listing detail: amenities, host, house rules, rating breakdown - NO price
listing = requests.post(f"{BASE}/api/v1/airbnb/listing", headers=HEADERS,
json={"listing_id": listing_id}).json()
print(listing["data"]["category_ratings"]) # cleanliness, accuracy, check-in, ...
# 3. Review bodies - always send limit explicitly, then step offset
reviews = requests.post(f"{BASE}/api/v1/airbnb/reviews", headers=HEADERS,
json={"listing_id": listing_id, "limit": 30, "offset": 0}).json()
print(reviews["data"]["count"], reviews["data"]["returned"]) # total vs this page
Paging: cursor or page, never both.
def search_pages(location, max_pages=3, **body):
"""18 listings per page, 1 credit per page."""
out, cursor = [], None
for _ in range(max_pages):
payload = {"location": location, **body}
if cursor:
payload["cursor"] = cursor # never alongside "page"
data = requests.post(f"{BASE}/api/v1/airbnb/search",
headers=HEADERS, json=payload).json()["data"]
out += data["listings"]
cursor = data["next_cursor"]
if not cursor:
break
return out
def all_reviews(listing_id, max_pages=4, limit=50):
out = []
for i in range(max_pages):
data = requests.post(f"{BASE}/api/v1/airbnb/reviews", headers=HEADERS,
json={"listing_id": listing_id,
"limit": limit, "offset": i * limit}).json()["data"]
out += data["reviews"]
if data["returned"] < limit or len(out) >= data["count"]:
break
return out
Response shapes
Every response uses the envelope { data, response_time, credits_used, credits_remaining }. Key data fields:
- search —
url,location,resolved_location,city,state,country,place_precision,coordinates,map_bounds,check_in,check_out,nights,dates_are_defaulted,currency,guests,page,page_count,next_cursor,count,listings[](pos,listing_id,listing_node_id,url,name,title,subtitle,rating,review_count,rating_label,bedrooms,beds,baths,price,badges,is_guest_favorite,is_superhost,coordinates,images). - listing —
listing_id,url,name,headline,description,description_html,summary,property_type,room_type,space_type,person_capacity,overview,bedrooms,beds,baths,rating,review_count,is_guest_favorite,is_new_listing,coordinates,address,neighborhood,breadcrumbs,host,amenities,amenity_groups,highlights,sleeping_arrangements,photo_tour,images,thumbnail,house_rules,safety_and_property,cancellation_policy,additional_house_rules,check_in_time,check_in_end_time,check_out_time,category_ratings[](category,label,rating). No price field of any kind. - reviews —
listing_id,url,count(the listing's total),rating,returned(this page),reviews[](id,text,rating,language,created_at,date,reviewer_id,reviewer_name,reviewer_photo).
{
"data": {
"location": "Austin, TX",
"check_in": "2026-09-08",
"check_out": "2026-09-13",
"nights": 5,
"dates_are_defaulted": false,
"currency": "USD",
"page": 1,
"page_count": 15,
"next_cursor": "eyJzZWN0aW9uX29mZnNldCI6...",
"count": 18,
"listings": [
{
"pos": 1,
"listing_id": "1234567890",
"name": "Sunny East Austin bungalow",
"rating": 4.92,
"review_count": 318,
"bedrooms": 2,
"beds": 3,
"baths": 1,
"is_guest_favorite": true,
"url": "https://www.airbnb.com/rooms/1234567890"
}
]
},
"credits_used": 1,
"credits_remaining": 999
}
Guardrails
- Every call is 1 credit, including one that comes back empty.
- Never quote a nightly rate from
/listing- there is none. Prices come from/searchonly. - Always check
dates_are_defaulted. If it istrue, Airbnb chose the window and A/B tested the prices; say so instead of presenting the figure as the user's dates. min_price/max_priceare the whole-stay total. If the user thinks in nightly terms, convert and tell them which one you filtered on.- Send
currencyon every call. Two identical requests without it can disagree. - Send
pageorcursor, never both - the request is rejected. - On
/reviews, always send an explicitlimit, and use exactlylimit/offset. The underscored variants silently return the same 7 rows forever. - Never invent a
room_typeor amenity name. Unrecognised values are rejected before the scrape precisely so the user is not billed for a filter Airbnb would have ignored. - Never fabricate listing names, prices, ratings, host details or review text. Only return what the API returned.
- Review text and host profiles are personal data about real people. Summarise; do not build profiles of individuals.
Failure handling
400means an invalid or missing parameter - an unpaired or out-of-order date,min_priceabovemax_price,pagesent together withcursor, or an unrecognisedroom_type/ amenity name. Fix and retry.401means the API key is invalid or missing. CheckSCAVIO_API_KEY.404means Airbnb could not resolve the location, or the listing id does not exist.429means rate or usage limit exceeded. Wait before retrying. See rate limits.502/503mean upstream is temporarily unavailable - wait a few seconds and retry, up to a few times. Airbnb occasionally serves a geo domain-switch interstitial; the transport already retries that internally, so a 502 that survives to you is real.- An empty result set is usually the filters - widen
max_price(remember it is the stay total), dropsuperhost/guest_favorite, or shorten the stay. - If
SCAVIO_API_KEYis not set, prompt the user to export it before continuing.
SDKs
pip install scavio==0.15.0
from scavio import ScavioClient
client = ScavioClient() # reads SCAVIO_API_KEY
found = client.airbnb.search("Austin, TX", check_in="2026-09-08", check_out="2026-09-13",
adults=2, max_price=1500, currency="USD")
listing_id = found["data"]["listings"][0]["listing_id"]
listing = client.airbnb.listing(listing_id) # amenities + rating breakdown, no price
reviews = client.airbnb.reviews(listing_id, limit=50, offset=0)
npm install scavio@0.15.0
import { Scavio } from "scavio";
const client = new Scavio(); // reads SCAVIO_API_KEY
const found = await client.airbnb.search({
location: "Austin, TX", check_in: "2026-09-08", check_out: "2026-09-13", currency: "USD",
});
const reviews = await client.airbnb.reviews({ listing_id: "1234567890", limit: 50, offset: 0 });
相关技能
从 AdMapix API 拉取广告创意、应用、榜单和收入预估等数据,原样返回结构化 JSON。
在本地磁盘以分类纯 Markdown 文件保存需要长期留存的事实,与智能体内置记忆并存。
诊断生产力系统反复失效的根因,给出最小干预——容量测算、瓶颈定位、可靠的本地记录。
把自然语言描述转为结构化 JSON,并由 mcp-diagram-generator MCP 服务生成 Draw.io、Mermaid 或 Excalidraw 图表文件。
编写、调试与调优 Playwright 测试,涵盖定位器策略、追踪诊断与 CI 友好的超时配置。
scavio-ai 的更多技能
浏览全部技能通过托管 OAuth 接入 GitHub REST API,覆盖仓库、Issue、PR、Commit、分支与用户等接口。
Pull a Facebook page's profile, posts, reels and photos, one post with its comments, a single reel/video with downloadable URLs, a public group and its posts, an event, and hashtag posts. 11 endpoints, 1 credit each, structured JSON.
Search the Meta Ad Library by keyword or Facebook Page id and walk full cursor pagination through every ad, with creative, run dates, platforms and political spend. 3 endpoints, 1 credit per page.
Search YouTube and retrieve videos, shorts, comments, transcripts, streams, channel data, and community posts with their comments as structured JSON. 17 endpoints across video and channel surfaces.
Search live or SOLD eBay listings, read a listing in full, and look up a seller's profile card as structured JSON. 3 endpoints, 1 credit each. Sold-listing search is the price-research feature eBay itself hides.
Search Google Hotels for a destination and dates, then fetch per-property vendor pricing and full details — as structured JSON. Price, rating, class, and amenity filters. v2 engine, 1 credit per request.