Metadata-Version: 2.4
Name: apify-booking-client
Version: 0.1.1
Summary: Python client for the rl1987/booking-api-scraper Apify Actor — Booking.com properties, live prices, and room-rate tables.
Author-email: rl1987 <rimantas@keyspace.lt>
License: MIT
Project-URL: Homepage, https://apify.com/rl1987/booking-api-scraper
Project-URL: Source, https://apify.com/rl1987/booking-api-scraper
Keywords: apify,web-scraping,api-client
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Dynamic: license-file

# apify-booking-client

**Booking.com properties, live prices, and full room-rate tables — by destination search or by hotel ID.**

Python client for the [`rl1987/booking-api-scraper`](https://apify.com/rl1987/booking-api-scraper) [Apify](https://apify.com) Actor. No local scraping, no proxy management, no anti-bot maintenance — the Actor runs on Apify's infrastructure and this package just starts it, waits, and hands you back the dataset as plain Python dicts.

[Install](#install) · [Quickstart](#quickstart) · [Getting an API token](#getting-an-api-token) · [Input reference](#input-reference) · [Output fields](#output-fields) · [Error handling](#error-handling) · [Pricing](#pricing) · [Async / long-running runs](#advanced-longer-timeouts--polling) · [Links](#links)

## Install

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

Requires Python 3.9+. Only dependency is [`requests`](https://pypi.org/project/requests/).

## Quickstart

```python
from apify_booking_client import BookingClient

client = BookingClient(api_token="apify_api_...")  # see "Getting an API token" below
items = client.run({"search": "Amsterdam", "rooms": 1, "adults": 2, "maxItems": 20})

for item in items:
    print(item)
```

Real output from the example above (trimmed to a few fields):

```python
{"id": 6331862, "currency": "USD", "checkin": "2026-09-23", "checkout": "2026-09-24", "url": "https://www.booking.com/hotel/nl/holiday-inn-express-amsterdam-motorkade.html?..."}
```

`run()` blocks until the Actor finishes (usually a few seconds to ~30s depending on `maxItems`) and returns a plain `list[dict]` — the Actor's dataset, one dict per result row.

## Getting an API token

1. Sign up for a free account at [console.apify.com](https://console.apify.com).
2. Go to **Settings → Integrations** and copy your **Personal API token**.
3. Pass it to the client: `BookingClient(api_token="...")`, or read it from an environment variable:

   ```python
   import os
   client = BookingClient(api_token=os.environ["APIFY_TOKEN"])
   ```

Never hardcode the token in source control — use an environment variable or secrets manager.

## Input reference

`run()` takes a single `dict` matching the Actor's input schema. Full/authoritative schema: the **Input** tab on [the Actor's Apify page](https://apify.com/rl1987/booking-api-scraper).

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `search` | str | — | Destination name, e.g. `"Amsterdam"`. Provide `search` or `hotel_ids`, or both. |
| `hotel_ids` | list[int] | — | Specific Booking.com hotel IDs to scrape directly, bypassing search. |
| `checkin` / `checkout` | str (`YYYY-MM-DD`) | +30 days / +1 night | Stay dates. |
| `rooms` | int | `1` | Number of rooms. |
| `adults` | int | `2` | Number of adult guests. |
| `currency` | str | `"USD"` | 3-letter currency code. |
| `sortBy` | str | `"none"` | `"none"`, `"price"`, or `"review_score"`. |
| `includeRooms` | bool | `False` | Add room-type and rate-product data per property. |
| `includeDetails` | bool | `False` | Add static details (name, star rating, facilities, address, photos). |
| `includeReviews` | bool | `False` | Add guest reviews. |
| `maxItems` | int | `100` | Maximum accommodations to return. |

## Output fields

Each dict in the returned list is one row from the Actor's dataset. Common fields:

`id`, `price`, `currency`, `checkin`, `checkout`, `url`, `deep_link_url`, plus `details`/`products`/`rooms`/`reviews` objects when the matching `include*` flag is set.

Exact field availability can vary by input flags (see table above) — treat unfamiliar/missing keys as optional and use `.get()` rather than `[...]` indexing.

## Error handling

```python
from apify_booking_client import BookingClient, ApifyActorError
import requests

client = BookingClient(api_token="...")

try:
    items = client.run({"search": "Amsterdam", "rooms": 1, "adults": 2, "maxItems": 20})
except ApifyActorError as e:
    # The Actor run itself failed, timed out, or was aborted on the Apify side.
    print(f"Actor run did not succeed: {e}")
except requests.HTTPError as e:
    # Bad token, malformed input, rate limiting, etc. — an HTTP-level error
    # calling the Apify API (not the Actor run).
    print(f"Apify API request failed: {e}")
```

`ApifyActorError` is raised when the run reaches a terminal non-success status (`FAILED`, `TIMED-OUT`, `ABORTED`) or doesn't finish within `timeout_secs` (default 300s — raise it for `run()` calls with a large `maxItems`, e.g. `BookingClient(api_token="...", timeout_secs=900)`).

## Pricing

Pay-per-event: $0.001/search result, $0.001/hotel-details row, $0.0001/room option, $0.0001/review. No subscription — see the [Actor's pricing tab](https://apify.com/rl1987/booking-api-scraper) for current rates. Apify also includes a free monthly usage tier that covers light use.

## Advanced: longer timeouts & polling

```python
client = BookingClient(api_token="...", timeout_secs=900)  # allow up to 15 min
items = client.run(actor_input, poll_interval_secs=3.0)   # poll less aggressively
```

## Links

- [Booking.com API Scraper on Apify](https://apify.com/rl1987/booking-api-scraper) — Actor page, input schema, pricing
- [PyPI package](https://pypi.org/project/apify-booking-client/)
- [Apify API reference](https://docs.apify.com/api/v2) — what this client wraps under the hood

## License

MIT
