Booking API endpoint
Returns Booking.com attractions/things-to-do search results for a destination and date range, with an optional category/subcategory filter and a discoverable category taxonomy.
/booking-attractions/searchquery (required): destination name or city, for example Paris.start_date (required): availability start date, YYYY-MM-DD.end_date: availability end date, YYYY-MM-DD. Defaults to start_date.page: 1-based result page. Defaults to 1.limit: results per page, 1-30. Defaults to 15.category: optional top-level category tagname filter, from a prior response's categories[].tagname, for example PTCMCcodv3rh.subcategory: optional subcategory tagname filter, from a prior response's categories[].subcategories[].tagname, for example PTCMCfzh93xC.category/subcategory are opaque, destination-specific tagnames — not a small fixed enum — so they are passed through without an allowlist; an unrecognized value is rejected by Booking.com directly. data.categories[] lists every available category/subcategory (with names and product counts) for the resolved destination so a caller can discover a valid filter value without visiting Booking.com. data.filtered_count/data.unfiltered_count only differ when a category/subcategory filter is applied.
| Field | Filled in, of 15 checked | Values in the sample |
|---|---|---|
| id | 15 | |
| name | 15 | “Seine River Sightseeing Cruise” and 14 other values |
| slug | 15 | |
| url | 15 | booking.com |
| description | 15 | “A one-hour boat tour through central Paris” and 14 other values |
| duration | 11 | “Duration: 1 hour - 1 hour 20 minutes” and 7 other values |
| price | 15 | 13.41 to 121.61, median 21.23 |
| currency | 15 | USD in all 15 |
| review_score | 14 | 3 to 4.6, median 4.3 |
| review_count | 14 | 2 to 7,280, median 1,201 |
| Parameter | Type | Required | Default | Description | Example |
|---|---|---|---|---|---|
| query | string | Yes | Destination name or city | Paris | |
| start_date | string | Yes | Availability start date, YYYY-MM-DD | 2026-09-15 | |
| end_date | string | No | start_date | Availability end date, YYYY-MM-DD, defaults to start_date | 2026-09-15 |
| page | integer | No | 1-based result page, default 1 | 1 | |
| limit | integer | No | Results per page, 1-30, default 15 | 15 | |
| category | string | No | Optional top-level category tagname filter, from a prior response's categories | PTCMCcodv3rh | |
| subcategory | string | No | Optional subcategory tagname filter, from a prior response's categories | PTCMCfzh93xC | |
| x-api-key (header) | string | Yes | API key required |
curl -X GET "https://api.crawlora.net/api/v1/booking-attractions/search?query=Paris&start_date=2026-09-15&page=1&limit=10" \ -H "x-api-key: $CRAWLORA_API_KEY"
{
"code": 200,
"msg": "OK",
"data": {
"query": "Paris",
"destination": "Paris",
"country": "fr",
"page": 1,
"has_next_page": true,
"filtered_count": 751,
"unfiltered_count": 2800,
"categories": [
{
"name": "Museums, arts & culture",
"tagname": "PTCMCcodv3rh",
"product_count": 751,
"subcategories": [
{
"name": "Cultural museums",
"tagname": "PTCMCfzh93xC",
"product_count": 471
}
]
}
],
"products": [
{
"id": "PRe4kSVWXdrD",
"name": "Seine River Sightseeing Cruise",
"slug": "pre4ksvwxdrd-seine-river-sightseeing-cruise",
"duration": "Duration: 1 hour",
"price": 18,
"currency": "EUR",
"review_score": 8.6,
"review_count": 4842
}
]
}
}Request schema
No body schema
Response schema
#/definitions/booking.bookingAttractionSearchResponseDoc
| Field | Type | Required | Enum | Bounds | Example | Description |
|---|---|---|---|---|---|---|
| code | integer | No | 200 | |||
| data | booking.AttractionSearchResponse | No | ||||
| data.categories | array | No | ||||
| data.categories[].name | string | No | ||||
| data.categories[].product_count | integer | No | ||||
| data.categories[].subcategories | array | No | ||||
| data.categories[].tagname | string | No | ||||
| data.country | string | No | ||||
| data.destination | string | No | ||||
| data.filtered_count | integer | No | ||||
| data.has_next_page | boolean | No | ||||
| data.page | integer | No | ||||
| data.products | array | No | ||||
| data.products[].currency | string | No | ||||
| data.products[].description | string | No | ||||
| data.products[].duration | string | No | ||||
| data.products[].id | string | No | ||||
| data.products[].name | string | No | ||||
| data.products[].price | number | No | ||||
| data.products[].review_count | integer | No | ||||
| data.products[].review_score | number | No | ||||
| data.products[].slug | string | No | ||||
| data.products[].url | string | No | ||||
| data.query | string | No | ||||
| data.unfiltered_count | integer | No | ||||
| msg | string | No | OK |
| Status | Description | Schema |
|---|---|---|
| 400 | Bad Request | #/definitions/app.Response |
| 404 | Not Found | #/definitions/app.Response |
| 429 | Too Many Requests | #/definitions/app.Response |
| 503 | Service Unavailable | #/definitions/app.Response |
Use environment variables for secrets and keep Crawlora API keys server-side.
curl -X GET "https://api.crawlora.net/api/v1/booking-attractions/search?query=Paris&start_date=2026-09-15&page=1&limit=10" \
-H "x-api-key: $CRAWLORA_API_KEY"