Airbnb Room URL Discovery Scraper
Pricing
Pay per event
Airbnb Room URL Discovery Scraper
Resolve Airbnb destinations and search URLs into deduplicated listing IDs, canonical room URLs, search positions, and compact discovery context.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Stas Persiianenko
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Turn public Airbnb destinations and search URLs into a clean inventory of canonical room URLs. The Actor returns stable listing IDs, search positions, page numbers, titles, room types, ratings, prices, images, and compact discovery context without opening every listing detail page.
Use it when the first step in your workflow is finding which Airbnb listings exist. It is intentionally a discovery Actor, not a full listing-detail, availability, or booking scraper.
What does this Airbnb scraper do?
The Actor accepts either:
- destination phrases such as
Barcelona, Spain; - public Airbnb search URLs ending in
/homes; or - both input types in one run.
It reads Airbnb's public search results, follows bounded pagination, creates canonical
https://www.airbnb.com/rooms/<listingId> URLs, and removes duplicate listing IDs across all inputs.
Filters already present in a supplied search URL—such as guest counts, bedroom counts, prices,
amenities, dates, or map bounds—are preserved.
Who is it for?
- Market researchers building destination-level accommodation inventories.
- Travel data teams preparing URL queues for later detail or availability enrichment.
- Analysts comparing listing presence across cities or recurring snapshots.
- Automation builders who need stable Airbnb listing IDs as join keys.
- Data engineers feeding room URLs into spreadsheets, databases, or downstream Actors.
Why use a URL discovery Actor?
Discovery and enrichment have different cost profiles. This Actor avoids requesting every room detail page when you only need an inventory first. That makes it useful for two-stage pipelines:
- discover candidate listing URLs cheaply;
- select the relevant IDs;
- enrich only those listings that matter.
Each record also keeps its source search, one-based position, and page number so you can trace where it came from.
What Airbnb data is extracted?
| Field | Meaning |
|---|---|
listingId | Stable numeric Airbnb listing ID |
listingUrl | Canonical public room URL |
searchInput | Original destination phrase or search URL |
sourceUrl | Normalized first-page URL |
searchUrl | Exact paginated URL where the result appeared |
searchPosition | One-based position within that source search |
pageNumber | One-based result page |
title | Listing subtitle/name from the search card |
roomType | Accommodation type shown in search |
rating | Average rating when available |
reviewCount | Parsed review count when available |
isSuperhost | Whether the card shows a Superhost badge |
thumbnailUrl | Primary search-card image |
latitude, longitude | Public search coordinates when available |
price | Localized price text for current filters |
priceQualifier | Price qualifier such as total |
scrapedAt | UTC extraction timestamp |
Some fields can be absent because new listings or particular card layouts do not expose them.
listingId and listingUrl are the core discovery output.
How to get started
- Open the Actor input page.
- Add one or more destinations, Airbnb search URLs, or both.
- Set
maxItemsto the maximum unique room URLs you need. - Set
maxPagesPerSearchto bound requests per input. - Choose a locale and currency if the displayed context matters.
- Run the Actor.
- Open the Results dataset view or export it as JSON, CSV, Excel, XML, or RSS.
A useful first run is:
{"destinations": ["Barcelona, Spain"],"maxItems": 20,"maxPagesPerSearch": 2,"locale": "en-US","currency": "USD"}
Input parameters
| Input | Type | Default | Notes |
|---|---|---|---|
destinations | string[] | — | Cities, regions, or destination phrases |
startUrls | URL[] | — | Public airbnb.com search URLs ending in /homes |
maxItems | integer | 100 | Global unique-record limit, from 1 to 1,000 |
maxPagesPerSearch | integer | 3 | Per-input page limit, from 1 to 15 |
locale | string | en-US | Language or language-country code |
currency | string | USD | Uppercase three-letter currency code |
proxyConfiguration | object | direct | Optional Apify or custom proxy settings |
At least one destination or search URL is required. The Actor rejects non-Airbnb URLs, room detail URLs, malformed locale values, and malformed currencies.
Using filtered Airbnb search URLs
Build filters on Airbnb first, then copy the resulting /homes URL into startUrls.
For example:
{"startUrls": [{"url": "https://www.airbnb.com/s/Amsterdam--Netherlands/homes?adults=2&min_bedrooms=1"}],"maxItems": 50,"maxPagesPerSearch": 3,"currency": "EUR"}
The Actor keeps the supplied query parameters when it requests later result pages. It does not silently replace the user's search scope.
Output example
A current result has this shape:
{"listingId": "5561974","listingUrl": "https://www.airbnb.com/rooms/5561974","searchInput": "Barcelona, Spain","sourceUrl": "https://www.airbnb.com/s/Barcelona--Spain/homes?locale=en-US¤cy=USD","searchUrl": "https://www.airbnb.com/s/Barcelona--Spain/homes?locale=en-US¤cy=USD","searchPosition": 1,"pageNumber": 1,"title": "1 Bed in shared 16 beds dorm","roomType": "Shared room in Barcelona","rating": 4.72,"reviewCount": 1655,"isSuperhost": true,"thumbnailUrl": "https://a0.muscache.com/im/pictures/example.jpeg","latitude": 41.38,"longitude": 2.17,"price": "$219 total","priceQualifier": "total","scrapedAt": "2026-08-05T12:00:00.000Z"}
Values change with dates, guest settings, locale, currency, and Airbnb's live inventory.
How much does it cost to discover Airbnb room URLs?
Pricing is pay per event: one start event per run plus one item event for each unique room URL saved.
The configuration charges a $0.0024 start fee.
Per-item prices decrease by Apify plan tier:
| Plan tier | Price per discovered room URL |
|---|---|
| Free | $0.003680 |
| Bronze | $0.003200 |
| Silver | $0.002496 |
| Gold | $0.001920 |
| Platinum | $0.001280 |
| Diamond | $0.000896 |
Examples before any separate platform subscription fees:
- 10 results on Free:
$0.0024 + 10 × $0.003680 = $0.0392. - 100 results on Bronze:
$0.0024 + 100 × $0.003200 = $0.3224. - 1,000 results on Gold:
$0.0024 + 1,000 × $0.001920 = $1.9224.
Only unique dataset records are charged as items. Duplicates and rejected records are not charged as output items. Optional proxy usage may add platform infrastructure usage depending on your Apify setup. Always check the live pricing panel for the applicable tier.
Pagination, limits, and deduplication
maxItems applies globally across every input in the run.
maxPagesPerSearch applies separately to each destination or URL.
The Actor stops scheduling pages once the global result limit is reached.
Deduplication uses the numeric Airbnb listing ID. If one listing appears in Barcelona and another supplied map/search URL, the first occurrence is kept. Its position remains the position in the source search before cross-search deduplication.
Search inventories are snapshots, not exhaustive declarations of every property that exists. Airbnb can personalize, reorder, insert, remove, or cap public results.
Scheduling and monitoring workflows
Use an Apify Schedule to run the same input daily or weekly.
Store each run's dataset in your destination system, then compare records by listingId.
Typical derived signals include:
- newly discovered listing IDs;
- IDs no longer visible in the selected search;
- position changes;
- changed rating or price text; and
- cross-city duplicates.
The Actor emits the snapshot; it does not itself send alerts or calculate historical diffs. Use an integration, webhook, or downstream workflow for those actions.
Export and integration options
The default dataset supports JSON, JSONL, CSV, Excel, XML, and RSS exports. Common patterns include:
- send new rows to Google Sheets;
- upsert by
listingIdinto a database; - enqueue
listingUrlvalues for a detail Actor; - trigger a webhook when a scheduled run finishes;
- join listing IDs with availability or host datasets; and
- compare snapshots in Python, SQL, or a data warehouse.
Because listingId is stable and listingUrl is canonical, both are convenient pipeline keys.
Run through the Apify API with cURL
curl -X POST \"https://api.apify.com/v2/acts/automation-lab~airbnb-room-url-discovery-scraper/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"destinations": ["Barcelona, Spain"],"maxItems": 20,"maxPagesPerSearch": 2}'
For production, prefer an Authorization: Bearer header instead of putting tokens in URLs.
Retrieve results from the run's default dataset ID.
Run through the Apify API with JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/airbnb-room-url-discovery-scraper').call({destinations: ['Amsterdam, Netherlands'],maxItems: 50,maxPagesPerSearch: 3,currency: 'EUR',});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.map(({ listingId, listingUrl }) => ({ listingId, listingUrl })));
Run through the Apify API with Python
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/airbnb-room-url-discovery-scraper').call(run_input={'destinations': ['Berlin, Germany'],'maxItems': 50,'maxPagesPerSearch': 3,'currency': 'EUR',})items = client.dataset(run['defaultDatasetId']).list_items().itemsprint([(item['listingId'], item['listingUrl']) for item in items])
Use with MCP and AI agents
Add the Actor to Claude Code through Apify MCP:
claude mcp add --transport http apify \"https://mcp.apify.com?tools=automation-lab/airbnb-room-url-discovery-scraper"
Claude Desktop
Add this server in Claude Desktop's MCP configuration:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=automation-lab/airbnb-room-url-discovery-scraper"}}}
Cursor
Use the same JSON server entry in Cursor's MCP settings, then enable the apify server.
VS Code
Add the same HTTP MCP server URL to your VS Code MCP configuration and start the server from the MCP panel.
Example prompts:
- “Discover 30 Airbnb room URLs in Barcelona and return listing IDs and positions.”
- “Resolve this filtered Amsterdam Airbnb search URL and save the result as CSV.”
- “Build one deduplicated listing inventory for Barcelona, Amsterdam, and Berlin.”
Tips for reliable results
- Supply Airbnb search URLs when exact filters matter.
- Use destination names with country or region context to avoid ambiguous places.
- Start with one or two pages before increasing scale.
- Keep scheduled inputs stable when comparing snapshots.
- Use dates and guest counts in the source URL when prices must be comparable.
- Leave proxy configuration disabled unless direct access fails in your environment.
- Do not interpret a missing result as proof that a listing was removed.
The Actor requests HTML and embedded public search state only; it does not download listing images.
Limitations and failure behavior
- Public Airbnb search results can be capped, reordered, personalized, or changed without notice.
- This Actor does not scrape complete room details, reviews, calendars, hosts, or booking availability.
- Search cards may omit ratings, review counts, coordinates, or prices.
- A destination phrase can be ambiguous; use a filtered Airbnb URL for exact scope.
- Login-only and private pages are unsupported.
- The Actor fails if every search is blocked or if Airbnb's structured page data is missing.
- In a mixed batch, successful searches are retained and failed searches are logged as warnings.
- The maximum supported output is 1,000 unique records per run.
Responsible and legal use
Scrape only public information you have a lawful purpose to process. Respect Airbnb's terms, applicable database rights, privacy laws, contractual obligations, and rate limits. Do not use the Actor to harass individuals, discriminate, evade access controls, or republish personal information unlawfully.
You are responsible for your input, retention policy, downstream processing, and compliance. This Actor is not affiliated with or endorsed by Airbnb.
Troubleshooting and FAQ
Why did my destination return the wrong area?
Use a more specific phrase such as Barcelona, Spain, or copy a search URL directly from Airbnb.
A URL with map bounds is the most precise option.
Why did I receive fewer items than maxItems?
The source may expose fewer results, the page limit may be reached, or duplicates may have been removed.
Increase maxPagesPerSearch only when the source has another cursor.
Why are price or rating fields missing?
Airbnb does not show every field on every search card. New listings can lack ratings, and price display depends on dates and guest filters.
What happens if Airbnb blocks a page?
The Actor retries bounded transient failures. If all searches fail, the run exits with an error instead of returning a misleading empty success. You can optionally configure an Apify or custom proxy.
Does it discover every Airbnb listing in a city?
No. It discovers the public results surfaced by the selected searches and page limits at run time. Use multiple precise map/search URLs if your research method requires broader coverage.
Can I provide room detail URLs?
No. This Actor resolves search scopes into room URLs. Use a listing detail Actor after discovery.
Related automation-lab Actors
- Airbnb Listing Scraper for deeper listing enrichment.
- Airbnb Host Portfolio Scraper for public host-to-listing relationships.
- Airbnb Shared Wishlist Scraper for room URLs and context from shared wishlists.
A common pipeline is discovery here, selective detail enrichment, then scheduled snapshot comparison.