Airbnb Listing Lookup: airbnb scraper by location from $2/1k
Pricing
from $1.52 / 1,000 listing returneds
Airbnb Listing Lookup: airbnb scraper by location from $2/1k
Airbnb listings scraper: search a location or paste an Airbnb search URL and get one row per listing, including price, rating, room type, coordinates, superhost status, and a direct link. No login. Pay per listing returned; empty searches are free.
Pricing
from $1.52 / 1,000 listing returneds
Rating
0.0
(0)
Developer
Adrian Voss
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Airbnb Listing Lookup
You give this actor a location ("Austin, TX") or a pasted Airbnb search URL. It runs the same search a browser would, reads the listings straight out of Airbnb's own search-results page, and gives you back one row per listing: price, rating, room type, coordinates, a Superhost/Guest Favorite badge, and a direct link. No login, no scraping a listing's own detail page — just the search-results card, the same thing you'd see scrolling the map view yourself.
Who it's for
If you're building a list of short-term-rental comps for a pricing model, sourcing candidate properties for a real-estate or arbitrage screen, or feeding an AI agent a "what's available and at what price in this city" question, this turns an Airbnb search into a table instead of a page you'd have to scroll and copy by hand. It answers "which listings, at what price, where, and how well-rated" for a location — not "tell me everything about this one listing", which is a heavier, separate lookup this actor deliberately doesn't make (see "Why this one").
Why this one
- Reads the search page's own embedded data, not a scraped-and-guessed DOM. Airbnb's search
results ship as a JSON blob inside the page (
__typename: "StaySearchResult"), the same data the page's own React code renders from — not text pulled off rendered HTML elements that change with every front-end redesign. - Priced per listing, not per search. A search for a big city can return dozens of listings; you pay $0.002 per listing actually returned, not a flat per-search fee, and a search that finds nothing costs nothing.
- Paginates automatically, up to 50 listings per search. One Airbnb search page ships 18 listings; this actor follows Airbnb's own next-page cursors (on the same residential proxy session, never a bare unproxied request) to gather up to 50 without you writing a page loop.
- Honest about what a search card can't tell you. Host ID and a full amenities list live only on a listing's own detail page — a much heavier per-listing hop this actor does not make. Rather than fake those fields, they're simply not in the output. See the FAQ for what the search card does carry instead (bedroom/bath counts, Superhost and Guest Favorite badges, rating).
- Never charged for a miss. A search with no results, a malformed location, or a proxy block all come back as a free row explaining why.
What you get
A parent row per search (columns below), exploded into one row per listing by default (turn off "One row per listing" in the Input tab to get one grouped row per search instead — you're charged the same either way).
| Field | Type | Description |
|---|---|---|
query | text | The search you submitted, echoed back |
found | boolean | true if at least one listing was returned |
status | text | OK on a match; NOT_FOUND, BLOCKED, BAD_FORMAT, or REQUEST_FAILED on a miss |
message | text | Plain-English reason for a miss — only present when found is false |
scrapedAt | ISO 8601 datetime | When the search was run |
searchInput | text | The location or URL you searched, echoed back |
checkin / checkout | text | The dates actually used for this search (from your input or the run's defaults) |
guests | number | The guest count actually used |
listingCount | number | How many listings this search returned (what you're billed for) |
truncated | boolean | true if Airbnb had more listings than this run returned |
listingId | text | Airbnb's own numeric listing ID |
url | link | The listing's airbnb.com/rooms/... page |
title | text | The listing's headline |
roomType | text | e.g. "Condo", "Private room", "Entire home" |
city | text | Parsed from the listing's category line |
lat / lng | number | Coordinates |
pricePerNight | number | Parsed from the price breakdown when a check-in/check-out range is in effect (see FAQ) |
priceCurrency | text | The currency symbol/code as Airbnb displayed it — not a verified ISO-4217 code |
priceDisplay | text | The price exactly as Airbnb showed it, for when the parsed number needs a sanity check |
rating | number | Out of 5 |
reviewCount | number | |
isSuperhost | boolean | |
isGuestFavorite | boolean | |
imageUrl | image | Cover photo |
Deselect any field in the Input tab's column picker to drop it from every row — the first five always stay.
Price
- Listing returned: $2 per 1,000 listings
Plus a $0.00005 start fee per run. Each event above is billed independently, only when it actually returns data — misses (found:false) are never charged.
$2 per 1,000 listings returned (FREE tier — less on a paid Apify plan), plus a $0.00005 actor-start
fee. A search that returns nothing costs nothing. 1,000 listings through this actor: ~$2 if
every search finds results. The store's leading incumbent, tri_angle/airbnb-scraper, charges $4
per 1,000 — this actor is half that, for the search-card fields (see "What you get") rather than a
full listing-detail crawl.
How to use
- In the Apify Console. Open the actor page and click Start — the
searchesfield is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found. - Via the API. Call it directly with a POST request — no Console needed once you have an API token:
curl "https://api.apify.com/v2/acts/accountable_eel~airbnb-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"searches":["Austin, TX"]}'
- On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
Input
{"searches": ["Austin, TX"]}
One search per line. Write a location like "Austin, TX" or "Lisbon, Portugal", or paste a full airbnb.com/s/.../homes search URL straight from your browser (dates and guest count in the URL are kept). Accepted formats: Austin, TX, Lisbon, Portugal, https://www.airbnb.com/s/Austin--TX/homes?checkin=2026-10-01&checkout=2026-10-05&adults=2.
Optional run-level settings (Input tab, "Search settings"): maxListings (default 18, capped at
50), checkin/checkout (YYYY-MM-DD), and guests — all ignored for any line that's already a
full search URL carrying its own dates and guest count.
Sample output
By default you get one row per listing (turn off "One row per listing" in the Input tab for one grouped row per search instead — you're charged the same either way):
| query | found | status | searchInput | checkin | checkout | guests | listingCount | truncated | listings | listingId | url | title | roomType | city | lat | lng | pricePerNight | priceCurrency | priceDisplay | rating | reviewCount | isSuperhost | isGuestFavorite | imageUrl | scrapedAt |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Austin, TX | false | NOT_FOUND | <all listings found (full list)> | <price per night (parsed)> | <currency (as displayed)> | <price (as airbnb displayed it)> | <superhost?> | <guest favorite?> | 2026-09-08T17:38:07.912Z |
A miss comes back as a row with "found": false and is never charged.
Use it from Clay, n8n, Make, or an AI agent
This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.
curl "https://api.apify.com/v2/acts/accountable_eel~airbnb-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"searches":["Austin, TX"]}'
n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~airbnb-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"searches":["Austin, TX"]} (swap in an expression from an earlier node for a real value).
Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~airbnb-listing-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"searches":["{{search}}"]}, mapping the row's search into the searches array.
MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Airbnb Listings Scraper by Location | Apify" — the agent will find and run this actor.
Tips
- Paste a full search URL (with your own
checkin/checkout/adultsparams already set) when you want exact control over dates and guests — a URL's own query params always win over the run-level defaults. - Leave check-in/check-out blank for a quick "what's generally available and at what price" sweep;
Airbnb picks its own default dates and the
checkin/checkoutoutput columns tell you what it used. truncated: truemeans more listings existed than this run returned — raise "Most listings to return per search" (up to 50) and run it again if you need the rest.- Keep "Max concurrency" conservative — this target runs on Residential proxy specifically because a bare datacenter request is not proven safe at volume (see "Why this one"), and a search-heavy burst is the fastest way to get a session blocked.
- If
pricePerNightcomes backnullon a listing that clearly has a price, checkpriceDisplay— it always carries Airbnb's raw price string even when the parser couldn't confidently split out a nightly rate from a total-for-stay figure.
vs. alternatives
| What it costs | What you get | Trade-off | |
|---|---|---|---|
This actor (airbnb-listing-lookup) | $0.002 per listing returned (FREE tier, less on paid tiers), $0.00005 actor start, nothing for a search with no results | One row per listing — price, rating, room type, coordinates, Superhost/Guest Favorite badges, and a direct link, from a location or a pasted search URL | Search-card data only: no host ID or amenities list (Airbnb doesn't ship either on the search results page — see FAQ), and price is parsed from a display string rather than a guaranteed ISO currency code. |
| tri_angle/airbnb-scraper | $4 per 1,000 results | The store's dominant incumbent — broader field coverage, including per-listing detail-page fields | If you need full listing-detail fields (complete amenities, host profile), that's a heavier per-listing hop this actor doesn't make. For the "which listings, at what price, where" question, this covers it at a quarter of the price. |
| Doing it yourself | Your time + reverse-engineering Airbnb's embedded GraphQL JSON (the query-variable key changes per search), cursor-based pagination, and residential-proxy economics | The same data | The JSON-path parsing, price-string extraction, pagination, and proxy handling are the maintenance burden this actor absorbs. |
Prices for third-party tools are their published list prices as of September 2026 and are not tracked here — check the vendor before relying on the comparison.
FAQ
Why don't I get a host ID or an amenities list?
Neither exists anywhere in the search-results page's own data — only on a listing's individual
page, a separate and much heavier per-listing fetch this actor doesn't make. Rather than fabricate
those fields from something else, they're simply not part of the output. What the search card does
carry: bedroom/bathroom counts folded into title/roomType, a rating, a review count, and
Superhost/Guest Favorite badges.
Is priceCurrency a real ISO currency code?
No — it's the currency symbol or code exactly as Airbnb displayed it (e.g. "Ft", "$", "€"), which
depends on the locale Airbnb resolved for the request. priceDisplay keeps the full original string
so you can always check it against pricePerNight.
Why is pricePerNight sometimes null?
Airbnb's search card only ships a pre-formatted price string, not a structured amount. This actor
recovers the nightly rate from the "N nights x [amount]" line in the price breakdown when a
check-in/check-out range is active; if that breakdown isn't present, pricePerNight stays null
rather than guessing — priceDisplay always has the raw figure regardless.
Am I charged for a search that finds nothing?
No. Actor.charge() only fires per listing actually returned. A search with zero results, a
malformed location, or a proxy block all produce a free row (unless you turn on "Hide rows with no
result").
Does this handle rate limits or blocking?
The default proxy is Residential specifically because this target is anti-bot-sensitive at volume.
A BLOCKED status means Airbnb returned HTTP 403/429/503 to the request; lowering "Max
concurrency" is the first thing to try.
Is this a live check or a stored database? Live. Every run is a fresh Airbnb search — there's no cached snapshot, and prices/availability reflect what Airbnb showed at fetch time, not a stored copy.
Can I schedule this to re-check the same search on a cadence? Yes — save it as an Apify Task with your input and add a Schedule. Each run is a fresh search, so a daily or weekly schedule is how you'd track price or availability changes for a location over time.
Can an AI agent call this directly? Yes. It's registered on the Apify MCP server — an agent in Claude, Cursor, or another MCP client can find and run it by name ("Airbnb Listings Scraper by Location | Apify"), or call the REST endpoint shown above from any script or workflow tool.
Related actors
- AutoScout24 Listing Lookup — the same one-request-per-listing pattern applied to Germany's largest car marketplace.
- Kleinanzeigen Listing Lookup — another Residential-proxy classifieds lookup in this catalogue.
- Sitemap URL Discovery — if you already have a target site and need every URL on it rather than a search result.