# Hotel Search: Kayak Prices from Every Booking Site (`bowmark-ai/hotel-search`) Actor

Search hotels in any city on Kayak and Cheapflights, which compare prices from many booking sites. Give a city and dates, get up to 50 hotels sorted by total price, with the cheapest booking site for each, ratings and a link.

- **URL**: https://apify.com/bowmark-ai/hotel-search.md
- **Developed by:** [Bowmark AI](https://apify.com/bowmark-ai) (community)
- **Categories:** Travel, MCP servers, Agents
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $89.00 / 1,000 hotel searches

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Hotel Search: Kayak Prices from Every Booking Site do?

Hotel Search looks up hotels in a city for your dates on **Kayak and Cheapflights**, which compare prices from many booking sites at once (Booking.com, Expedia, Agoda, Priceline, Hotels.com and hotels' own websites). You get one list, sorted by total price.

Give it a city and dates. For every search it returns up to 50 hotels, each with the whole-stay price, the nightly rate, **which booking site sells it cheapest and how many sites quoted it**, star class, guest score and review count, neighbourhood, distance and a link. Each row also picks out the cheapest stay and the cheapest well-reviewed stay, so you can read the answer without opening the list.

It never books, buys or signs in anywhere. It only reads the public search results.

### Why use it?

- **One search, every booking site.** Single-site scrapers show you one site's price. This shows the lowest price any of them is offering, and who is offering it.
- **Compare many cities or dates.** Put dozens of searches in one run, schedule it, and export the table to a spreadsheet.
- **AI agents.** Connect it as an MCP server and let an agent find a place to stay while it plans a trip.

### How it works

For each search it reads, at the same time:

1. **Kayak** hotel search
2. **Cheapflights** hotel search

The same hotel listed on both appears once, at its cheapest price. Results are sorted cheapest total first. If one site does not answer in time, the row says so, so a partial search never looks complete.

### Input

| Field | Required | Description |
|---|---|---|
| `searches` | Yes | One entry per city and stay. Each needs a `location` (a city name like `Lisbon`, or an airport code like `LIS`), a `checkIn` date (`YYYY-MM-DD`, or `"+30"` for 30 days from today) and either `checkOut` or `nights`. Optional: `adults` (total guests, default 2) and `rooms` (default 1). A line like `"Lisbon 2026-12-10 2026-12-13"` works too. |
| `maxConcurrency` | No | Searches run at once, 1 to 8. Default `4`. |

Example input:

```json
{
  "searches": [
    { "location": "Lisbon", "checkIn": "2026-12-10", "checkOut": "2026-12-13" },
    { "location": "LAS", "checkIn": "2026-12-04", "nights": 2, "adults": 4, "rooms": 2 },
    "Austin 2026-12-04 2026-12-06"
  ]
}
```

### Output

One dataset row per search. Download it as JSON, CSV, Excel or HTML, or read it through the Apify API.

```json
{
  "location": "Austin",
  "checkIn": "2026-12-04",
  "checkOut": "2026-12-06",
  "status": "found",
  "cheapestPrice": 176,
  "cheapestNightPrice": 75,
  "currency": "USD",
  "cheapestHotel": "Scottish Inns Austin Downtown",
  "cheapestSeller": "Priceline",
  "cheapestUrl": "https://www.cheapflights.com/hotels/Scottish-Inns-Austin-Downtown,Austin-p56642-h65996-details/2026-12-04/2026-12-06/2adults",
  "bestValueHotel": "Hampton Inn & Suites Austin Cedar Park-Lakeline",
  "bestValuePrice": 180,
  "bestValueScore": 8.6,
  "hotelCount": 50,
  "hotels": [
    {
      "source": "cheapflights", "name": "Scottish Inns Austin Downtown",
      "price": 176, "nightPrice": 75, "currency": "USD",
      "seller": "Priceline", "sellerCount": 4, "stars": 2,
      "score": 5.8, "reviewCount": 487, "propertyType": "Hotel",
      "city": "Austin", "distance": "3.8 mi", "distanceFrom": "from city center",
      "url": "https://www.cheapflights.com/hotels/Scottish-Inns-Austin-Downtown,Austin-p56642-h65996-details/2026-12-04/2026-12-06/2adults"
    }
  ],
  "warnings": [],
  "error": null
}
```

`status` is `found`, `not_found` or `error`. `not_found` means the sites answered and listed nothing for that place and those dates, which is a real answer (a sold-out weekend, or a place too small to have hotels listed).

`price` is the whole stay: every night and every room. `nightPrice` is the advertised rate for one room for one night, often before taxes and fees, so compare hotels on `price`. `bestValueHotel` is the cheapest hotel with a guest score of 8 or more from at least 50 reviews. `stars` is `null` for places with no star class, like apartments and hostels.

### Pricing

**$0.088 per search**, with no monthly fee. One search returns up to 50 hotels with prices from every booking site Kayak compares, not one page of one site.

- A search that comes back `not_found` is charged, because both sites were still searched.
- A search that fails with an error is not charged.
- Set a spending limit on the run and the Actor stops cleanly when it reaches it.
- On Apify's free plan, each run processes the first 10 searches (10 tool calls per MCP session). Any paid Apify plan removes the limit.

### Use it as an MCP server

This Actor also runs as an MCP server with one tool, `search_hotels`. Point any MCP client (Claude, Cursor, ChatGPT, your own agent) at:

```
https://bowmark-ai--hotel-search.apify.actor/mcp
```

with your Apify API token as a bearer token. Each tool call is billed like one search in a normal run.

### Limits and good practice

- It reads only **public** search results. It never signs in anywhere and never changes anything.
- Use a city name (`Austin`) or an airport code (`AUS`). A state or country after a comma is dropped, because the sites search nothing for "Austin, TX".
- Prices are in US dollars and come from the comparison sites, so a hotel's own website can occasionally differ.
- Each search takes about 20 to 60 seconds. Use dates in the future.
- Cheapest first means hostels and shared rooms often lead. Use `bestValueHotel`, or filter `hotels` on `stars`, `score` and `propertyType`.

### Questions or a wrong result?

Open an issue on the **Issues** tab with the input you used and what you expected. We read every one.

# Actor input Schema

## `searches` (type: `array`):

One entry per city and stay, up to 500 per run (10 on Apify's free plan). Each needs a location (a city name like Lisbon, or an airport code like LIS), a checkIn date (YYYY-MM-DD, or "+30" for 30 days from today) and either a checkOut date or a number of nights. Optional: adults (total guests, default 2) and rooms (default 1). A line like "Lisbon 2026-12-10 2026-12-13" works too.

## `maxConcurrency` (type: `integer`):

How many searches run in parallel.

## Actor input object example

```json
{
  "searches": [
    {
      "location": "LIS",
      "checkIn": "+30",
      "nights": 2
    }
  ],
  "maxConcurrency": 4
}
```

# Actor output Schema

## `results` (type: `string`):

One row per search: the cheapest stay, the cheapest well-reviewed stay, and every hotel found.

# 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 = {
    "searches": [
        {
            "location": "LIS",
            "checkIn": "+30",
            "nights": 2
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bowmark-ai/hotel-search").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 = { "searches": [{
            "location": "LIS",
            "checkIn": "+30",
            "nights": 2,
        }] }

# Run the Actor and wait for it to finish
run = client.actor("bowmark-ai/hotel-search").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 '{
  "searches": [
    {
      "location": "LIS",
      "checkIn": "+30",
      "nights": 2
    }
  ]
}' |
apify call bowmark-ai/hotel-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bowmark-ai/hotel-search"
        }
    }
}
```

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/EIREivck4q8jtavAH/builds/WjAt7lIKY4cQccbu0/openapi.json
