# VRBO Vacation Rentals Scraper (`devilscrapes/vrbo-vacation-rentals-scraper`) Actor

Scrape VRBO (Expedia Group) vacation-rental search results and listing details by destination: title, location, price per night, beds/baths, guests, rating, reviews, amenities, host, and coordinates. Camoufox-powered to clear anti-bot challenges. Pay only per listing scraped.

- **URL**: https://apify.com/devilscrapes/vrbo-vacation-rentals-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Travel
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## VRBO Vacation Rentals Scraper

**💰 $2.82 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*We do the dirty work so your dataset stays clean.* 😈

Give this Actor a list of destinations and get back structured VRBO (Expedia Group) vacation-rental listing rows — title, location, price per night, beds/baths, guests, rating, reviews, amenities, host, and coordinates where public.

</div>

***

### 🎯 What this scrapes

For each destination string you pass in (VRBO's own free-text search box format, e.g. `"Orlando, Florida, United States of America"`), this Actor:

1. Opens a rendered VRBO search-results page for that destination and your check-in/check-out window.
2. Captures up to your configured cap of listing cards — title, location, price per night, currency, bedrooms, bathrooms, and max guests.
3. Optionally visits each listing's detail page for the fuller field set: rating, review count, amenities, host name, and latitude/longitude.
4. Emits one row per listing to the default dataset, tagged with the destination query that found it.

### 🔥 Features

- **We clear the JS-execution gate VRBO puts in front of raw HTTP requests** — a hardened browser layer renders the page like a real visitor instead of bouncing off a "Bot or Not?" challenge screen.
- **We rotate residential proxy sessions** through Apify Proxy — a fresh exit IP and session on every block.
- **We back off when the target pushes back.** Partial successes surface with a clear status message — we never silently return an empty dataset.
- **Run-wide wall-clock budget** — the run stops opening new pages once your time budget is spent and finalizes cleanly with whatever it already scraped, instead of getting killed mid-write.
- **Per-listing fault isolation** — one dead page or navigation timeout skips that listing with a logged warning; it never fails the whole run.
- **Pydantic v2 input + output validation** — every row is a typed, schema-enforced record; nullable fields are always `null`, never silently dropped.
- **Pay-Per-Event pricing** — you're charged per listing row written to your dataset, not per page fetched.

### 💡 Use cases

- **Market research** — compare nightly rates, bedroom counts, and amenities across destinations for a vacation-rental market scan.
- **Revenue-management benchmarking** — property managers pull comparable listings to sanity-check their own pricing.
- **Travel-content sourcing** — bulk-pull listing photos-adjacent metadata (title, location, rating) for roundup articles or itinerary tools.
- **Lead generation** — identify active hosts and listings in a target destination for partnership or outreach lists.

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Add 1-10 destination strings (VRBO's own free-text search format works best).
3. Optionally set check-in/check-out dates — otherwise the Actor defaults to a near-future window so results actually populate.
4. Click **Start**. Output streams into the run's dataset.
5. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `destinations` | `array` | **yes** | — | 1-10 free-text VRBO destination search queries. |
| `checkin` | `string` | no | +30 days from run date | Search window start (`YYYY-MM-DD`). |
| `checkout` | `string` | no | +33 days from run date | Search window end (`YYYY-MM-DD`), must be after `checkin`. |
| `maxListingsPerDestination` | `integer` | no | `20` | 1-50 listing rows collected per destination. |
| `scrapeListingDetails` | `boolean` | no | `true` | If `false`, search-card fields only (cheaper, faster). |
| `maxRunMinutes` | `integer` | no | `12` | Run-wide wall-clock budget; stop opening new pages past this. |
| `proxyConfiguration` | `object` | no | `RESIDENTIAL` | Apify Proxy — mandatory, falls back to `BUYPROXIES94952`. |

#### Example input

```json
{
  "destinations": ["Orlando, Florida, United States of America"],
  "checkin": "2026-09-10",
  "checkout": "2026-09-13",
  "maxListingsPerDestination": 20,
  "scrapeListingDetails": true,
  "maxRunMinutes": 12,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

### 📤 Output

Every row is one dataset item — one VRBO listing.

| Field | Type | Notes |
|---|---|---|
| `destination_query` | string | The destination string that discovered this row. |
| `listing_url` | string | Canonical VRBO listing URL. |
| `title` | string | Listing title. |
| `location` | string | Listing location as displayed by VRBO. |
| `price_per_night` | float | null | Nightly price for the searched window. |
| `currency` | string | ISO currency code. |
| `bedrooms` | integer | null | Bedroom count. |
| `bathrooms` | float | null | Bathroom count. |
| `max_guests` | integer | null | Max occupancy. |
| `rating` | float | null | Aggregate rating (detail-page field). |
| `reviews_count` | integer | null | Review count (detail-page field). |
| `amenities` | array | Amenity labels (detail-page field). |
| `host_name` | string | null | Host display name (detail-page field). |
| `latitude` | float | null | Listing latitude, where public. |
| `longitude` | float | null | Listing longitude, where public. |
| `scraped_at` | string | ISO-8601 UTC timestamp. |

Nullable fields are `null`, never omitted, when VRBO doesn't expose them publicly or `scrapeListingDetails` was `false`.

#### Example output

```json
{
  "destination_query": "Orlando, Florida, United States of America",
  "listing_url": "https://www.vrbo.com/1234567ha",
  "title": "Lakefront Cabin near Disney with Private Pool",
  "location": "Orlando, Florida, United States",
  "price_per_night": 189.0,
  "currency": "USD",
  "bedrooms": 3,
  "bathrooms": 2.0,
  "max_guests": 8,
  "rating": 4.8,
  "reviews_count": 214,
  "amenities": ["Pool", "Wifi", "Kitchen", "Air conditioning"],
  "host_name": "Jane D.",
  "latitude": 28.3852,
  "longitude": -81.5639,
  "scraped_at": "2026-08-11T12:00:00.000Z"
}
```

### 💰 Pricing

Pay-Per-Event — you pay only when these events fire:

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.02 | One-off warm-up charge per run. |
| `result-row` | $0.0028 | Per listing row written to your dataset. |

Example: 1 000 results at the rates above ≈ **$2.82**. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.

### 🚧 Limitations

v0.1 covers destination-string search only — no booking/availability-calendar scraping, no pricing quotes beyond the single search window used to populate results, no review text (aggregate rating + review count only), and no host-profile enrichment beyond the name shown on the listing. Map/geo bounding-box search is not supported.

### ❓ FAQ

**Is this legal?**

We only fetch content VRBO makes publicly available on its search and listing pages. Respect VRBO's terms of service before using output commercially.

**Why is a field `null`?**

Detail-page fields (`rating`, `reviews_count`, `amenities`, `host_name`, `latitude`, `longitude`) are `null` when `scrapeListingDetails` is `false`, or when VRBO doesn't expose that field publicly for a given listing.

**Do I need my own proxy?**

No — Apify Proxy (residential) is wired in by default.

**Why did I get fewer rows than `maxListingsPerDestination`?**

The run-wide `maxRunMinutes` budget stops opening new pages once it's spent, and any listing that hits a dead page or navigation timeout is skipped rather than failing the run — check the run's status message for a breakdown.

### 💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an
issue on the Actor's **Issues** tab on Apify Console — we ship
fixes weekly and we read every report.

***

<div align="center">

Built by **[Devil Scrapes](https://apify.com/DevilScrapes)** 😈 — a small fleet of
opinionated public-data Actors. Honest pricing, real engineering, zero fine print.

</div>

# Actor input Schema

## `destinations` (type: `array`):

1-10 free-text VRBO destination search queries, e.g. "Orlando, Florida, United States of America".

## `checkin` (type: `string`):

Search window start (YYYY-MM-DD). Defaults to +30 days from run date when omitted.

## `checkout` (type: `string`):

Search window end (YYYY-MM-DD), must be after Check-in date. Defaults to +33 days from run date when omitted.

## `maxListingsPerDestination` (type: `integer`):

Cap on listing rows collected per destination.

## `scrapeListingDetails` (type: `boolean`):

When true, also visit each listing's detail page for rating, reviews, amenities, host, and coordinates. When false, emit search-card fields only (cheaper, faster).

## `maxRunMinutes` (type: `integer`):

Run-wide wall-clock budget; the run stops opening new pages past this and finalizes with whatever was scraped.

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

Apify Proxy — mandatory. Defaults to RESIDENTIAL; falls back to BUYPROXIES94952 on accounts without RESIDENTIAL provisioned.

## Actor input object example

```json
{
  "destinations": [
    "Orlando, Florida, United States of America"
  ],
  "maxListingsPerDestination": 20,
  "scrapeListingDetails": true,
  "maxRunMinutes": 12,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "destinations": [
        "Orlando, Florida, United States of America"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/vrbo-vacation-rentals-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 = {
    "destinations": ["Orlando, Florida, United States of America"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/vrbo-vacation-rentals-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "destinations": [
    "Orlando, Florida, United States of America"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call devilscrapes/vrbo-vacation-rentals-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/vrbo-vacation-rentals-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/vgMYcBjbKiBvxkkfk/builds/2rz1KqeeB9B0DDGMe/openapi.json
