# Airbnb Guest Origin Scraper – Guest Demographics by Country (`integrative_tangent/airbnb-guest-origin-scraper`) Actor

Discover WHERE Airbnb guests come from. Extracts reviewer locations from listing reviews (public data, no login) and aggregates guest demographics by country and region — per listing and per market. Search by location, bounding box, URL, or listing IDs.

- **URL**: https://apify.com/integrative\_tangent/airbnb-guest-origin-scraper.md
- **Developed by:** [Luis Segura](https://apify.com/integrative_tangent) (community)
- **Categories:** Real estate, Travel
- **Stats:** 2 total users, 1 monthly users, 20.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Airbnb Guest Origin Scraper – Guest Demographics by Country

Discover **where Airbnb guests actually come from**. This actor extracts reviewer locations from Airbnb listing reviews (100% public data — no account or login required) and turns them into ready-to-use **guest demographic breakdowns by country and region**, per listing and per market.

**No account required. No API key needed.**

---

### Why this data is valuable

Official tourism statistics tell you who enters a country — they never tell you who stays in short-term rentals, or in which exact neighborhood. This actor fills that gap:

- **Hosts & property managers** — adapt your listing to your real guest mix (hot water expectations, plug adapters, welcome book language, coffee vs. tea) and target your ads where your guests actually live. If 40% of your guests are Canadian, advertise in Canada.
- **STR investors** — before buying in a zone, see which nationalities visit it and whether they match your price segment.
- **Tourism boards & DMOs** — hyperlocal source-market data for vacation rentals that exists in no official statistic.
- **Market researchers & consultancies** — origin-of-demand studies by micro-zone, with year-over-year trend data included.

### What You Get

Three row types in one dataset:

#### 1. `review` rows — one per review
| Field | Description |
|---|---|
| `listingId`, `listingUrl`, `listingTitle` | The listing |
| `reviewerName`, `reviewerId` | The guest |
| `date`, `rating`, `language` | Review metadata |
| `reviewerLocationRaw` | Location exactly as shown on Airbnb, e.g. "Brooklyn, New York" |
| `country` | Normalized country — "United States" |
| `countryCode` | ISO code — "US" |
| `region` | "North America", "Europe", "Caribbean", ... |

#### 2. `listing_summary` rows — one per listing
Full demographic profile: `byCountry` (count + % per country), `byRegion`, `topCountry`, `locationCoveragePct`, `distinctCountries`.

#### 3. `global_summary` row — one per run
The whole market aggregated, plus `byYearTopCountries` — top source countries per review year, so you can see demand trends (e.g. Canadian share growing 2022→2025).

### How to Use It

**Analyze a whole market** (easiest):
```json
{ "location": "Lisbon, Portugal", "maxListings": 50 }
````

**Analyze specific listings:**

```json
{ "urls": ["https://www.airbnb.com/rooms/48711480"], "maxReviewsPerListing": 0 }
```

**Summaries only** (cheapest for market studies):

```json
{ "location": "Tulum, Mexico", "maxListings": 100, "emitReviewRows": false }
```

Also supports Airbnb search URLs and raw GPS bounding boxes.

### Sample Output

```json
{
  "type": "listing_summary",
  "listingId": "48711480",
  "reviewsScraped": 100,
  "reviewsWithLocation": 87,
  "locationCoveragePct": 87,
  "distinctCountries": 12,
  "topCountry": "United States",
  "topCountryPct": 43.68,
  "byCountry": [
    { "country": "United States", "countryCode": "US", "count": 38, "pct": 43.68 },
    { "country": "Canada", "countryCode": "CA", "count": 14, "pct": 16.09 },
    { "country": "France", "countryCode": "FR", "count": 9, "pct": 10.34 }
  ],
  "byRegion": [
    { "region": "North America", "count": 52, "pct": 59.77 },
    { "region": "Europe", "count": 21, "pct": 24.14 }
  ]
}
```

### How it works

The actor reads the same public reviews data Airbnb shows on every listing page, including the reviewer's self-reported location. Locations are then normalized (handles English, Spanish, French, German and Portuguese location strings, US states, Canadian provinces, and 200+ major cities) into canonical countries and regions.

- Reviews are fetched most-recent-first.
- `maxReviewsPerListing: 0` fetches every review for maximum accuracy.
- Not every reviewer sets a location — expect 60–90% coverage; the exact coverage is reported per listing (`locationCoveragePct`).

### Pricing & Cost

Pay per result. Every dataset row (review, listing summary, global summary) is one result.

| Scenario | Rows (approx.) |
|---|---|
| 1 listing, 100 reviews | ~101 |
| 50 listings × 100 reviews | ~5,051 |
| 100 listings, summaries only | ~101 |

Tip: for market studies, `emitReviewRows: false` gives you the full demographic picture at ~1% of the cost.

### Proxy Recommendations

| Volume | Proxy |
|---|---|
| < 20 listings | None needed |
| 20–100 listings | Apify residential recommended |
| 100+ listings | Apify residential required |

### Limitations

- Reviewer location is self-reported and optional — coverage is typically 60–90%, never 100%.
- Locations resolve to country level; city-level analysis is possible from `reviewerLocationRaw`.
- Unrecognized/ambiguous locations are kept raw with `country: null` so you never lose data.

### Legal

This actor collects only publicly visible data shown to any anonymous visitor on airbnb.com listing pages. It does not access private profiles, does not log in, and does not collect contact information. Please use the data in compliance with applicable laws and Airbnb's terms.

# Actor input Schema

## `listingIds` (type: `array`):

Specific Airbnb listing IDs. These are the numeric codes in Airbnb URLs — e.g. airbnb.com/rooms/48711480 → ID is "48711480".

Example: \["48711480", "1506456228556318996"]

## `urls` (type: `array`):

Full Airbnb listing URLs. The actor extracts the listing ID automatically.

Example: \["https://www.airbnb.com/rooms/48711480"]

## `searchUrl` (type: `string`):

An Airbnb search results URL containing map coordinates (ne\_lat, ne\_lng, sw\_lat, sw\_lng). The actor discovers all listings in that map area.

How to get it: search on airbnb.com, move the map to your area, then copy the URL from your browser.

## `boundingBox` (type: `object`):

Define a custom geographic area using GPS coordinates: northeast (top-right) and southwest (bottom-left) corners.

Example for Miami Beach:
{"ne\_lat": 25.85, "ne\_lng": -80.11, "sw\_lat": 25.75, "sw\_lng": -80.15}

## `location` (type: `string`):

City, neighborhood, or region name. The actor geocodes it via OpenStreetMap and discovers every listing in the area.

Examples: "Miami Beach, Florida" · "Lisbon, Portugal" · "Tulum, Mexico" · "Bali, Indonesia"

## `maxListings` (type: `integer`):

Cap on how many listings to process. Set to 0 for unlimited.

Tip: Start with 5–10 to test before running a full market analysis.

## `maxReviewsPerListing` (type: `integer`):

How many reviews to fetch per listing (most recent first). Set to 0 to fetch ALL reviews — best demographic accuracy, but slower and more results billed.

## `emitReviewRows` (type: `boolean`):

When enabled (default), each review becomes a dataset row with the reviewer's origin. When disabled, only the per-listing and global demographic summaries are emitted — much cheaper for pure market studies.

## `includeReviewText` (type: `boolean`):

Include the full review comment text in review rows. Off by default to keep the dataset light.

## `proxyConfiguration` (type: `object`):

Apify Residential proxy is used by default and strongly recommended — Airbnb blocks datacenter IPs, which causes empty or failed runs. Only disable it if you provide your own proxy.

## Actor input object example

```json
{
  "listingIds": [
    "48711480"
  ],
  "maxListings": 1,
  "maxReviewsPerListing": 20,
  "emitReviewRows": true,
  "includeReviewText": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "listingIds": [
        "48711480"
    ],
    "maxListings": 1,
    "maxReviewsPerListing": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("integrative_tangent/airbnb-guest-origin-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "listingIds": ["48711480"],
    "maxListings": 1,
    "maxReviewsPerListing": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("integrative_tangent/airbnb-guest-origin-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "listingIds": [
    "48711480"
  ],
  "maxListings": 1,
  "maxReviewsPerListing": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call integrative_tangent/airbnb-guest-origin-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=integrative_tangent/airbnb-guest-origin-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Airbnb Guest Origin Scraper – Guest Demographics by Country",
        "description": "Discover WHERE Airbnb guests come from. Extracts reviewer locations from listing reviews (public data, no login) and aggregates guest demographics by country and region — per listing and per market. Search by location, bounding box, URL, or listing IDs.",
        "version": "1.0",
        "x-build-id": "hr3IZKYwRh4pYXzru"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/integrative_tangent~airbnb-guest-origin-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-integrative_tangent-airbnb-guest-origin-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/integrative_tangent~airbnb-guest-origin-scraper/runs": {
            "post": {
                "operationId": "runs-sync-integrative_tangent-airbnb-guest-origin-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/integrative_tangent~airbnb-guest-origin-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-integrative_tangent-airbnb-guest-origin-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "listingIds": {
                        "title": "Listing IDs",
                        "type": "array",
                        "description": "Specific Airbnb listing IDs. These are the numeric codes in Airbnb URLs — e.g. airbnb.com/rooms/48711480 → ID is \"48711480\".\n\nExample: [\"48711480\", \"1506456228556318996\"]",
                        "items": {
                            "type": "string"
                        }
                    },
                    "urls": {
                        "title": "Listing URLs",
                        "type": "array",
                        "description": "Full Airbnb listing URLs. The actor extracts the listing ID automatically.\n\nExample: [\"https://www.airbnb.com/rooms/48711480\"]",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchUrl": {
                        "title": "Search URL",
                        "type": "string",
                        "description": "An Airbnb search results URL containing map coordinates (ne_lat, ne_lng, sw_lat, sw_lng). The actor discovers all listings in that map area.\n\nHow to get it: search on airbnb.com, move the map to your area, then copy the URL from your browser."
                    },
                    "boundingBox": {
                        "title": "Bounding Box Coordinates",
                        "type": "object",
                        "description": "Define a custom geographic area using GPS coordinates: northeast (top-right) and southwest (bottom-left) corners.\n\nExample for Miami Beach:\n{\"ne_lat\": 25.85, \"ne_lng\": -80.11, \"sw_lat\": 25.75, \"sw_lng\": -80.15}"
                    },
                    "location": {
                        "title": "Location Name",
                        "type": "string",
                        "description": "City, neighborhood, or region name. The actor geocodes it via OpenStreetMap and discovers every listing in the area.\n\nExamples: \"Miami Beach, Florida\" · \"Lisbon, Portugal\" · \"Tulum, Mexico\" · \"Bali, Indonesia\""
                    },
                    "maxListings": {
                        "title": "Maximum Listings",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Cap on how many listings to process. Set to 0 for unlimited.\n\nTip: Start with 5–10 to test before running a full market analysis.",
                        "default": 0
                    },
                    "maxReviewsPerListing": {
                        "title": "Maximum Reviews per Listing",
                        "minimum": 0,
                        "type": "integer",
                        "description": "How many reviews to fetch per listing (most recent first). Set to 0 to fetch ALL reviews — best demographic accuracy, but slower and more results billed.",
                        "default": 100
                    },
                    "emitReviewRows": {
                        "title": "Emit One Row per Review",
                        "type": "boolean",
                        "description": "When enabled (default), each review becomes a dataset row with the reviewer's origin. When disabled, only the per-listing and global demographic summaries are emitted — much cheaper for pure market studies.",
                        "default": true
                    },
                    "includeReviewText": {
                        "title": "Include Review Text",
                        "type": "boolean",
                        "description": "Include the full review comment text in review rows. Off by default to keep the dataset light.",
                        "default": false
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Apify Residential proxy is used by default and strongly recommended — Airbnb blocks datacenter IPs, which causes empty or failed runs. Only disable it if you provide your own proxy.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
