Arcadium Data Scrapers
Home / Actors / Booking.com Hotel Prices Scraper

Booking.com Hotel Prices Scraper

Give it Booking.com hotel links or IDs, or a city, plus check-in dates and nights, and it returns one JSON row per hotel and stay: the cheapest total price, every room rate (meal plan, cancellation, taxes and fees), a sold-out flag, stars and review score. $2.70 per 1,000 rows on the free plan, less on paid plans; you pay only for rows you get.

$2.70 per 1,000 price rows on the Free plan, down to $2.58 on higher plans

Why this actor

Drop-in input

Drop-in input. Input written for voyager/booking-scraper (search, checkIn, checkOut, minScore, starsCountFilter, minMaxPrice, sortBy, search-result startUrls), santamaria-automations/booking-com-scraper (destination, checkin, checkout) or rl1987/booking-api-scraper (search, hotel_ids, windowDays, stayNights) works as it is.

As stated in the actor’s README. The full list of accepted input names is on the Store page.

Switching from another actor

What you get

FieldWhat it holds
hotelId, hotelName, hotelUrlBooking.com id, name and page link.
stars, reviewScore, reviewCountStar rating, guest score on the 0-10 scale, number of reviews.
propertyType, city, countryCode, addressWhere it is and what kind of property it is (hotel lookups give all four; destination rows give city, country and address).
checkIn, checkOut, nights, adults, children, roomsThe stay this row is about.
currencyCurrency of every price in the row.
available, soldOutWhether the hotel can be booked for the stay. A sold-out row has no price.
minPrice, minPricePerNightCheapest total for the whole stay (all rooms) and per night.
originalPriceThe same rate before discounts.
taxesAndFeesExcludedTaxes and fees shown as "excluded" on the site (for example VAT and city tax paid on top).
mealPlan, freeCancellation, cancellationPolicy, cheapestRoomMeal plan (ROOM_ONLY, BREAKFAST, HALF_BOARD, ...), whether the cheapest rate has free cancellation, free_cancellation or non_refundable, and the room it is for.
roomRatesEvery rate for the stay: room, meal plan, price, per night, original price, taxes, cancellation (with the site's wording), prepayment. Cheapest first.
rateCount, sourceHow many rates, and where they come from: roomTable (every rate) or search (the cheapest rate of each hotel).
searchDestination, searchRankDestination searches: the text you gave and the hotel's position in the results.
changeWatch mode: type (new, price_drop, price_rise, availability, rates), fields (old -> new), previousCheckAt, previousMinPrice, priceChange.
scrapedAtWhen the row was read.

Sample row (from the README example; long text shortened, lists cut to two items):

{
  "rowType": "price",
  "platform": "booking",
  "hotelId": "55103",
  "hotelName": "Hôtel De La Paix",
  "hotelUrl": "https://www.booking.com/hotel/fr/de-la-paix-paris1.html",
  "stars": 3,
  "reviewScore": 8.5,
  "reviewCount": 2112,
  "city": "Paris",
  "countryCode": "fr",
  "checkIn": "2026-12-10",
  "checkOut": "2026-12-12",
  "nights": 2,
  "adults": 2,
  "children": 0,
  "rooms": 1,
  "currency": "EUR",
  "available": true,
  "soldOut": false,
  "minPrice": 236.73,
  "minPricePerNight": 118.37,
  "originalPrice": 338.18,
  "taxesAndFeesExcluded": 45.79,
  "mealPlan": "ROOM_ONLY",
  "freeCancellation": false,
  "cancellationPolicy": "non_refundable",
  "cheapestRoom": "Standard Double Room",
  "roomRates": [
    {
      "roomName": "Standard Double Room",
      "mealPlan": "ROOM_ONLY",
      "price": 236.73,
      "pricePerNight": 118.37,
      "cancellation": "non_refundable",
      "cancellationText": "Non-refundable",
      "payment": "prepayment_required"
    }
  ],
  "rateCount": 12,
  "source": "roomTable",
  "scrapedAt": "2026-10-21T08:00:00.000Z"
}

Price

Live Apify price on 2026-11-01, per 1,000 rows, by Apify plan. You pay only for rows delivered; error and summary rows marked free in the README cost nothing. Plus $0.001 per GB of memory when a run starts.

Per 1,000FreeBronzeSilverGoldPlatinumDiamond
Price row (main)$2.70$2.67$2.64$2.58$2.58$2.58

Use cases

Run it from code or an AI agent

Actor ID arcadium/booking-prices. Set APIFY_TOKEN to your Apify API token. The input below is the actor’s prefilled example; see the guide for every field.

curl
curl -X POST "https://api.apify.com/v2/acts/arcadium~booking-prices/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"startUrls":[{"url":"https://www.booking.com/hotel/fr/de-la-paix-paris1.html"}],"destinationType":"CITY","maxHotels":20,"checkInDates":["+30d"],"nights":[1],"childrenAges":[],"currency":"EUR","includeRoomRates":false,"watch":false,"watchKey":"default","digest":false,"digestDays":7}'
JavaScript
// npm install apify-client
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/booking-prices').call({
  "startUrls": [
    {
      "url": "https://www.booking.com/hotel/fr/de-la-paix-paris1.html"
    }
  ],
  "destinationType": "CITY",
  "maxHotels": 20,
  "checkInDates": [
    "+30d"
  ],
  "nights": [
    1
  ],
  "childrenAges": [],
  "currency": "EUR",
  "includeRoomRates": false,
  "watch": false,
  "watchKey": "default",
  "digest": false,
  "digestDays": 7
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
Python
# pip install apify-client
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/booking-prices").call(run_input={
    "startUrls": [{
        "url": "https://www.booking.com/hotel/fr/de-la-paix-paris1.html",
    }],
    "destinationType": "CITY",
    "maxHotels": 20,
    "checkInDates": ["+30d"],
    "nights": [1],
    "childrenAges": [],
    "currency": "EUR",
    "includeRoomRates": False,
    "watch": False,
    "watchKey": "default",
    "digest": False,
    "digestDays": 7,
})
items = client.dataset(run.default_dataset_id).list_items().items  # apify-client 3.x returns a Run object
print(items)
MCP
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=arcadium/booking-prices",
      "headers": {
        "Authorization": "Bearer <APIFY_TOKEN>"
      }
    }
  }
}
LangChain
# pip install langchain-apify   (reads APIFY_API_TOKEN from the environment)
from langchain_apify import ApifyActorsTool

tool = ApifyActorsTool("arcadium/booking-prices")
rows = tool.invoke({"run_input": {
    "startUrls": [{
        "url": "https://www.booking.com/hotel/fr/de-la-paix-paris1.html",
    }],
    "destinationType": "CITY",
    "maxHotels": 20,
    "checkInDates": ["+30d"],
    "nights": [1],
    "childrenAges": [],
    "currency": "EUR",
    "includeRoomRates": False,
    "watch": False,
    "watchKey": "default",
    "digest": False,
    "digestDays": 7,
}})
# or give `tool` to an agent: create_react_agent(llm, [tool])
LlamaIndex
# pip install llama-index-readers-apify
import os
from llama_index.core import Document, VectorStoreIndex
from llama_index.readers.apify import ApifyActor

reader = ApifyActor(os.environ["APIFY_TOKEN"])
documents = reader.load_data(
    actor_id="arcadium/booking-prices",
    run_input={
        "startUrls": [{
            "url": "https://www.booking.com/hotel/fr/de-la-paix-paris1.html",
        }],
        "destinationType": "CITY",
        "maxHotels": 20,
        "checkInDates": ["+30d"],
        "nights": [1],
        "childrenAges": [],
        "currency": "EUR",
        "includeRoomRates": False,
        "watch": False,
        "watchKey": "default",
        "digest": False,
        "digestDays": 7,
    },
    dataset_mapping_function=lambda item: Document(text=str(item.get("title") or ""), metadata={"url": item.get("url")}),
)
index = VectorStoreIndex.from_documents(documents)
CrewAI
# pip install crewai crewai-tools langchain-apify   (reads APIFY_API_TOKEN from the environment)
from crewai import Agent
from crewai_tools import ApifyActorsTool

tool = ApifyActorsTool(actor_name="arcadium/booking-prices")
researcher = Agent(
    role="Research analyst",
    goal="Answer with data collected by the tool",
    backstory="Uses public web data.",
    tools=[tool],
)
n8n
{
  "nodes": [
    {
      "name": "Run arcadium/booking-prices",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        0,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.apify.com/v2/acts/arcadium~booking-prices/run-sync-get-dataset-items",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "{\"startUrls\":[{\"url\":\"https://www.booking.com/hotel/fr/de-la-paix-paris1.html\"}],\"destinationType\":\"CITY\",\"maxHotels\":20,\"checkInDates\":[\"+30d\"],\"nights\":[1],\"childrenAges\":[],\"currency\":\"EUR\",\"includeRoomRates\":false,\"watch\":false,\"watchKey\":\"default\",\"digest\":false,\"digestDays\":7}",
        "options": {
          "timeout": 300000
        }
      }
    }
  ],
  "connections": {}
}
Google Sheets
// Extensions > Apps Script. Store your token once: Project Settings > Script properties > APIFY_TOKEN.
function importLastRun() {
  const token = PropertiesService.getScriptProperties().getProperty('APIFY_TOKEN');
  const url = 'https://api.apify.com/v2/acts/arcadium~booking-prices/runs/last/dataset/items?status=SUCCEEDED&clean=true&format=json';
  const res = UrlFetchApp.fetch(url, { headers: { Authorization: 'Bearer ' + token } });
  const rows = JSON.parse(res.getContentText());
  if (!rows.length) return;
  const keys = Object.keys(rows[0]);
  const values = rows.map((r) => keys.map((k) => (typeof r[k] === 'object' ? JSON.stringify(r[k]) : r[k])));
  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.clearContents();
  sheet.getRange(1, 1, 1, keys.length).setValues([keys]);
  sheet.getRange(2, 1, values.length, keys.length).setValues(values);
}

Tutorials

Limitations

FAQ

Why is a date missing for a hotel? Either it did not match your filters (no error row is added) or the date was rejected (past, too far ahead); rejected dates get a free error row.

How do I find a hotel id? It is the number in the hotelId field of any row, and the actor accepts the hotel page link instead.

What does a sold-out row mean? Booking.com had no rate for the dates and guests you asked for. The row is delivered (and charged) because the availability is the information; turn on watch to get it only when it changes.

Something looks wrong in the output. Who do I tell? Open an issue on the actor page with the run link. We read them all.

Related actors

Agoda and Trip.com Reviews Scraper

Agoda and Trip.com hotel reviews for hotel links or IDs: score, original text, English translation if any, hotel reply; $5.40 per 1,000 Agoda reviews.

$5.40 per 1,000 Agoda reviews on the Free plan, down to $2.70 on higher plans

Booking.com Reviews Scraper

Booking.com hotel reviews for hotel URLs: score, liked and disliked text, hotel reply, reviewer country, traveler type, stay details; $1.80 per 1,000 reviews.

$1.80 per 1,000 reviews on the Free plan, down to $0.81 on higher plans

Google Hotel Reviews Scraper

Google hotel reviews for hotel links or names: rating, text, translation, date, trip type, room/service/location scores, owner reply; $0.54 per 1,000 reviews.

$0.54 per 1,000 reviews on the Free plan, down to $0.27 on higher plans

Google Hotels Scraper

Google Hotels prices for a city or hotel and dates, $4.49 per 1,000 hotels; zerobreak/google-hotels-scraper input works as is (23% of its runs failed, Oct 2026).

$4.49 per 1,000 hotel rows on the Free plan, down to $2.69 on higher plans

Hotel Reviews Scraper

Hotel reviews from Tripadvisor, Booking.com, Google Hotels, Agoda and Trip.com in one dataset, ratings on one 1-5 scale; $4.50 per 1,000 reviews.

$4.50 per 1,000 reviews on the Free plan, down to $0.80 on higher plans

Tripadvisor Reviews Scraper

Tripadvisor reviews for hotel, restaurant and attraction URLs or place names: rating, text, date, owner reply, sub-ratings; $4.50 per 1,000 reviews.

$4.50 per 1,000 reviews on the Free plan, down to $0.80 on higher plans