hotelzero 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +521 -0
- package/dist/browser.d.ts +119 -0
- package/dist/browser.js +731 -0
- package/dist/debug-filters.d.ts +1 -0
- package/dist/debug-filters.js +72 -0
- package/dist/debug-sponsored.d.ts +1 -0
- package/dist/debug-sponsored.js +87 -0
- package/dist/debug.d.ts +1 -0
- package/dist/debug.js +37 -0
- package/dist/extract-filters.d.ts +1 -0
- package/dist/extract-filters.js +96 -0
- package/dist/final-test.d.ts +1 -0
- package/dist/final-test.js +46 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +494 -0
- package/dist/test-mcp.d.ts +1 -0
- package/dist/test-mcp.js +61 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +37 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# HotelZero
|
|
2
|
+
|
|
3
|
+
An MCP (Model Context Protocol) server that searches hotels on Booking.com using Playwright browser automation. Features 80+ filter options for precise hotel searches.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Comprehensive Filtering**: 80+ filters covering property types, amenities, accessibility, activities, and more
|
|
8
|
+
- **Real Booking.com Data**: Uses actual Booking.com filter codes reverse-engineered from their URL parameters
|
|
9
|
+
- **Sponsored Ad Filtering**: Automatically excludes paid/promoted listings (native ads with `nad_` tracking)
|
|
10
|
+
- **Smart Scoring**: Results are scored and ranked by how well they match your criteria
|
|
11
|
+
- **Match Transparency**: Each result shows why it matched your filters
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g hotelzero
|
|
17
|
+
|
|
18
|
+
# Install Playwright browser (Chromium)
|
|
19
|
+
npx playwright install chromium
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or run directly with npx:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx hotelzero
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
### Run as MCP Server
|
|
31
|
+
|
|
32
|
+
Add to your MCP client configuration (e.g., Claude Desktop, OpenCode):
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"hotelzero": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["hotelzero"]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Available Tools
|
|
46
|
+
|
|
47
|
+
### `find_hotels`
|
|
48
|
+
|
|
49
|
+
Search for hotels with comprehensive filtering. This is the primary tool with all 80+ filter options.
|
|
50
|
+
|
|
51
|
+
**Example:**
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"destination": "San Juan, Puerto Rico",
|
|
55
|
+
"checkIn": "2026-03-07",
|
|
56
|
+
"checkOut": "2026-03-14",
|
|
57
|
+
"beachfront": true,
|
|
58
|
+
"freeWifi": true,
|
|
59
|
+
"fitness": true,
|
|
60
|
+
"minRating": 8
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### `search_hotels`
|
|
65
|
+
|
|
66
|
+
Basic hotel search without filters. Use this for simple queries when you don't need specific criteria.
|
|
67
|
+
|
|
68
|
+
**Example:**
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"destination": "Paris, France",
|
|
72
|
+
"checkIn": "2026-06-01",
|
|
73
|
+
"checkOut": "2026-06-05",
|
|
74
|
+
"guests": 2,
|
|
75
|
+
"rooms": 1
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### `get_hotel_details`
|
|
80
|
+
|
|
81
|
+
Get detailed information about a specific hotel including full amenity list, description, and photos.
|
|
82
|
+
|
|
83
|
+
**Example:**
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"url": "https://www.booking.com/hotel/pr/condado-vanderbilt.html"
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Complete Filter Reference
|
|
93
|
+
|
|
94
|
+
### Basic Search Parameters
|
|
95
|
+
|
|
96
|
+
| Parameter | Type | Required | Description |
|
|
97
|
+
|-----------|------|----------|-------------|
|
|
98
|
+
| `destination` | string | Yes | City or location (e.g., "San Juan, Puerto Rico") |
|
|
99
|
+
| `checkIn` | string | Yes | Check-in date (YYYY-MM-DD) |
|
|
100
|
+
| `checkOut` | string | Yes | Check-out date (YYYY-MM-DD) |
|
|
101
|
+
| `guests` | number | No | Number of guests (default: 2) |
|
|
102
|
+
| `rooms` | number | No | Number of rooms (default: 1) |
|
|
103
|
+
|
|
104
|
+
### Rating & Price
|
|
105
|
+
|
|
106
|
+
| Filter | Type | Description |
|
|
107
|
+
|--------|------|-------------|
|
|
108
|
+
| `minRating` | number | Minimum review score: 6=Pleasant, 7=Good, 8=Very Good, 9=Wonderful |
|
|
109
|
+
| `maxPrice` | number | Maximum price per night in USD (client-side filter) |
|
|
110
|
+
|
|
111
|
+
### Property Type
|
|
112
|
+
|
|
113
|
+
| Filter | Type | Options |
|
|
114
|
+
|--------|------|---------|
|
|
115
|
+
| `propertyType` | enum | `hotel`, `apartment`, `resort`, `villa`, `vacation_home`, `hostel`, `bnb`, `guesthouse`, `homestay`, `motel`, `inn`, `lodge`, `chalet`, `campground`, `glamping`, `boat`, `capsule`, `ryokan`, `riad`, `country_house`, `farm_stay` |
|
|
116
|
+
| `starRating` | number | 1, 2, 3, 4, or 5 stars |
|
|
117
|
+
|
|
118
|
+
### Beach & Location
|
|
119
|
+
|
|
120
|
+
| Filter | Type | Description |
|
|
121
|
+
|--------|------|-------------|
|
|
122
|
+
| `beachfront` | boolean | Property is directly on the beach |
|
|
123
|
+
| `beachAccess` | boolean | Property has beach access |
|
|
124
|
+
| `oceanView` | boolean | Room with ocean/sea view |
|
|
125
|
+
| `maxDistanceFromCenter` | enum | `half_mile`, `1_mile`, `2_miles` |
|
|
126
|
+
|
|
127
|
+
### Hotel Facilities
|
|
128
|
+
|
|
129
|
+
| Filter | Description |
|
|
130
|
+
|--------|-------------|
|
|
131
|
+
| `freeWifi` | Free WiFi throughout property |
|
|
132
|
+
| `pool` | Swimming pool |
|
|
133
|
+
| `spa` | Spa/wellness center |
|
|
134
|
+
| `fitness` | Fitness center/gym |
|
|
135
|
+
| `parking` | Parking available |
|
|
136
|
+
| `restaurant` | On-site restaurant |
|
|
137
|
+
| `bar` | On-site bar/lounge |
|
|
138
|
+
| `roomService` | 24-hour front desk/room service |
|
|
139
|
+
| `airportShuttle` | Airport shuttle service |
|
|
140
|
+
| `hotTub` | Hot tub/Jacuzzi |
|
|
141
|
+
| `sauna` | Sauna |
|
|
142
|
+
| `garden` | Garden |
|
|
143
|
+
| `terrace` | Terrace |
|
|
144
|
+
| `nonSmokingRooms` | Non-smoking rooms available |
|
|
145
|
+
| `familyRooms` | Family rooms |
|
|
146
|
+
| `evCharging` | Electric vehicle charging station |
|
|
147
|
+
| `casino` | Casino |
|
|
148
|
+
| `golf` | Golf course nearby (within 2 miles) |
|
|
149
|
+
| `tennis` | Tennis court |
|
|
150
|
+
| `bbqFacilities` | BBQ facilities |
|
|
151
|
+
| `laundry` | Laundry service |
|
|
152
|
+
| `concierge` | Concierge service |
|
|
153
|
+
| `businessCenter` | Business center |
|
|
154
|
+
|
|
155
|
+
### Room Facilities
|
|
156
|
+
|
|
157
|
+
| Filter | Description |
|
|
158
|
+
|--------|-------------|
|
|
159
|
+
| `airConditioning` | Air conditioning |
|
|
160
|
+
| `kitchen` | Kitchen or kitchenette |
|
|
161
|
+
| `balcony` | Private balcony |
|
|
162
|
+
| `privatePool` | Private pool |
|
|
163
|
+
| `privateBathroom` | Private bathroom |
|
|
164
|
+
| `bath` | Bathtub |
|
|
165
|
+
| `tv` | Television |
|
|
166
|
+
| `minibar` | Minibar |
|
|
167
|
+
| `safe` | In-room safe |
|
|
168
|
+
| `washingMachine` | Washing machine in unit |
|
|
169
|
+
| `soundproofing` | Soundproofed rooms |
|
|
170
|
+
|
|
171
|
+
### Bed Type
|
|
172
|
+
|
|
173
|
+
| Filter | Options |
|
|
174
|
+
|--------|---------|
|
|
175
|
+
| `bedType` | `king`, `queen`, `double`, `twin`, `single` |
|
|
176
|
+
|
|
177
|
+
### Meal Plans
|
|
178
|
+
|
|
179
|
+
| Filter | Description |
|
|
180
|
+
|--------|-------------|
|
|
181
|
+
| `breakfast` | Breakfast included in rate |
|
|
182
|
+
| `allInclusive` | All-inclusive package |
|
|
183
|
+
| `selfCatering` | Self-catering with kitchen amenities |
|
|
184
|
+
|
|
185
|
+
### Stay Type & Policies
|
|
186
|
+
|
|
187
|
+
| Filter | Description |
|
|
188
|
+
|--------|-------------|
|
|
189
|
+
| `petFriendly` | Pets allowed |
|
|
190
|
+
| `adultsOnly` | Adults-only property |
|
|
191
|
+
| `lgbtqFriendly` | LGBTQ+ friendly (Booking.com Travel Proud) |
|
|
192
|
+
| `freeCancellation` | Free cancellation available |
|
|
193
|
+
| `noPrepayment` | No prepayment required |
|
|
194
|
+
| `noBookingFee` | Book without credit card |
|
|
195
|
+
|
|
196
|
+
### Sustainability
|
|
197
|
+
|
|
198
|
+
| Filter | Description |
|
|
199
|
+
|--------|-------------|
|
|
200
|
+
| `sustainabilityCertified` | Has sustainability certification |
|
|
201
|
+
|
|
202
|
+
### Activities
|
|
203
|
+
|
|
204
|
+
| Filter | Description |
|
|
205
|
+
|--------|-------------|
|
|
206
|
+
| `snorkeling` | Snorkeling available |
|
|
207
|
+
| `diving` | Diving/scuba available |
|
|
208
|
+
| `fishing` | Fishing available |
|
|
209
|
+
| `hiking` | Hiking trails nearby |
|
|
210
|
+
| `cycling` | Cycling/biking available |
|
|
211
|
+
| `skiing` | Skiing nearby |
|
|
212
|
+
| `waterSports` | Water sports available |
|
|
213
|
+
| `horseRiding` | Horse riding available |
|
|
214
|
+
|
|
215
|
+
### Accessibility - Property Level
|
|
216
|
+
|
|
217
|
+
| Filter | Description |
|
|
218
|
+
|--------|-------------|
|
|
219
|
+
| `grabRails` | Grab rails in bathroom |
|
|
220
|
+
| `raisedToilet` | Raised toilet |
|
|
221
|
+
| `loweredSink` | Lowered sink |
|
|
222
|
+
| `braille` | Braille signage |
|
|
223
|
+
| `tactileSigns` | Tactile signs |
|
|
224
|
+
| `auditoryGuidance` | Auditory guidance |
|
|
225
|
+
|
|
226
|
+
### Accessibility - Room Level
|
|
227
|
+
|
|
228
|
+
| Filter | Description |
|
|
229
|
+
|--------|-------------|
|
|
230
|
+
| `wheelchairAccessible` | Entire unit wheelchair accessible |
|
|
231
|
+
| `groundFloor` | Ground floor unit available |
|
|
232
|
+
| `elevatorAccess` | Upper floors accessible by elevator |
|
|
233
|
+
| `walkInShower` | Walk-in shower |
|
|
234
|
+
| `rollInShower` | Roll-in shower (wheelchair accessible) |
|
|
235
|
+
| `showerChair` | Shower chair available |
|
|
236
|
+
|
|
237
|
+
### Hotel Chains
|
|
238
|
+
|
|
239
|
+
| Filter | Options |
|
|
240
|
+
|--------|---------|
|
|
241
|
+
| `hotelChain` | `marriott`, `hilton`, `hyatt`, `ihg`, `wyndham`, `best_western`, `accor`, `choice`, `radisson`, `ritz_carlton`, `four_seasons`, `fairmont`, `sheraton`, `westin`, `w_hotels`, `courtyard`, `residence_inn`, `hampton`, `embassy_suites`, `doubletree` |
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Example Queries
|
|
246
|
+
|
|
247
|
+
### Beach Vacation in Puerto Rico
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"destination": "San Juan, Puerto Rico",
|
|
252
|
+
"checkIn": "2026-03-07",
|
|
253
|
+
"checkOut": "2026-03-14",
|
|
254
|
+
"beachfront": true,
|
|
255
|
+
"freeWifi": true,
|
|
256
|
+
"fitness": true,
|
|
257
|
+
"pool": true,
|
|
258
|
+
"minRating": 8
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Luxury Ski Resort
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"destination": "Aspen, Colorado",
|
|
267
|
+
"checkIn": "2026-01-15",
|
|
268
|
+
"checkOut": "2026-01-22",
|
|
269
|
+
"propertyType": "resort",
|
|
270
|
+
"starRating": 5,
|
|
271
|
+
"skiing": true,
|
|
272
|
+
"spa": true,
|
|
273
|
+
"hotTub": true,
|
|
274
|
+
"minRating": 9
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Family Beach Trip with All-Inclusive
|
|
279
|
+
|
|
280
|
+
```json
|
|
281
|
+
{
|
|
282
|
+
"destination": "Cancun, Mexico",
|
|
283
|
+
"checkIn": "2026-07-01",
|
|
284
|
+
"checkOut": "2026-07-08",
|
|
285
|
+
"guests": 4,
|
|
286
|
+
"rooms": 2,
|
|
287
|
+
"beachfront": true,
|
|
288
|
+
"allInclusive": true,
|
|
289
|
+
"familyRooms": true,
|
|
290
|
+
"pool": true,
|
|
291
|
+
"freeCancellation": true
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Accessible City Center Hotel
|
|
296
|
+
|
|
297
|
+
```json
|
|
298
|
+
{
|
|
299
|
+
"destination": "London, UK",
|
|
300
|
+
"checkIn": "2026-04-01",
|
|
301
|
+
"checkOut": "2026-04-05",
|
|
302
|
+
"maxDistanceFromCenter": "half_mile",
|
|
303
|
+
"wheelchairAccessible": true,
|
|
304
|
+
"elevatorAccess": true,
|
|
305
|
+
"walkInShower": true,
|
|
306
|
+
"freeWifi": true
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Pet-Friendly Road Trip Stop
|
|
311
|
+
|
|
312
|
+
```json
|
|
313
|
+
{
|
|
314
|
+
"destination": "Portland, Oregon",
|
|
315
|
+
"checkIn": "2026-05-10",
|
|
316
|
+
"checkOut": "2026-05-12",
|
|
317
|
+
"petFriendly": true,
|
|
318
|
+
"parking": true,
|
|
319
|
+
"freeCancellation": true,
|
|
320
|
+
"maxPrice": 200
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Digital Nomad Long Stay
|
|
325
|
+
|
|
326
|
+
```json
|
|
327
|
+
{
|
|
328
|
+
"destination": "Lisbon, Portugal",
|
|
329
|
+
"checkIn": "2026-06-01",
|
|
330
|
+
"checkOut": "2026-06-30",
|
|
331
|
+
"propertyType": "apartment",
|
|
332
|
+
"kitchen": true,
|
|
333
|
+
"freeWifi": true,
|
|
334
|
+
"washingMachine": true,
|
|
335
|
+
"maxDistanceFromCenter": "1_mile",
|
|
336
|
+
"maxPrice": 150
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Romantic Getaway
|
|
341
|
+
|
|
342
|
+
```json
|
|
343
|
+
{
|
|
344
|
+
"destination": "Santorini, Greece",
|
|
345
|
+
"checkIn": "2026-09-15",
|
|
346
|
+
"checkOut": "2026-09-20",
|
|
347
|
+
"adultsOnly": true,
|
|
348
|
+
"oceanView": true,
|
|
349
|
+
"privatePool": true,
|
|
350
|
+
"breakfast": true,
|
|
351
|
+
"spa": true,
|
|
352
|
+
"minRating": 9
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Japanese Cultural Experience
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"destination": "Kyoto, Japan",
|
|
361
|
+
"checkIn": "2026-04-01",
|
|
362
|
+
"checkOut": "2026-04-07",
|
|
363
|
+
"propertyType": "ryokan",
|
|
364
|
+
"breakfast": true,
|
|
365
|
+
"minRating": 8
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Eco-Friendly Adventure
|
|
370
|
+
|
|
371
|
+
```json
|
|
372
|
+
{
|
|
373
|
+
"destination": "Costa Rica",
|
|
374
|
+
"checkIn": "2026-02-01",
|
|
375
|
+
"checkOut": "2026-02-08",
|
|
376
|
+
"sustainabilityCertified": true,
|
|
377
|
+
"hiking": true,
|
|
378
|
+
"snorkeling": true,
|
|
379
|
+
"diving": true
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Golf Trip
|
|
384
|
+
|
|
385
|
+
```json
|
|
386
|
+
{
|
|
387
|
+
"destination": "Scottsdale, Arizona",
|
|
388
|
+
"checkIn": "2026-03-01",
|
|
389
|
+
"checkOut": "2026-03-05",
|
|
390
|
+
"propertyType": "resort",
|
|
391
|
+
"golf": true,
|
|
392
|
+
"spa": true,
|
|
393
|
+
"restaurant": true,
|
|
394
|
+
"bar": true
|
|
395
|
+
}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## How It Works
|
|
401
|
+
|
|
402
|
+
### Server-Side Filtering
|
|
403
|
+
|
|
404
|
+
Filters are applied via Booking.com's `nflt` URL parameter using reverse-engineered filter codes. For example:
|
|
405
|
+
|
|
406
|
+
- `beachfront: true` adds `ht_beach=1`
|
|
407
|
+
- `freeWifi: true` adds `hotelfacility=107`
|
|
408
|
+
- `fitness: true` adds `popular_activities=11`
|
|
409
|
+
- `minRating: 8` adds `review_score=80`
|
|
410
|
+
|
|
411
|
+
### Client-Side Scoring
|
|
412
|
+
|
|
413
|
+
After fetching results, each hotel is scored based on how well it matches your criteria:
|
|
414
|
+
|
|
415
|
+
- **+20 points**: Beach-related filters when property mentions beach
|
|
416
|
+
- **+15 points**: Rating 9.0+ ("Excellent")
|
|
417
|
+
- **+10 points**: Each matched amenity (WiFi, pool, gym, etc.)
|
|
418
|
+
- **+5 points**: 500+ reviews (trustworthiness bonus)
|
|
419
|
+
|
|
420
|
+
Results are sorted by match score, so the best matches appear first.
|
|
421
|
+
|
|
422
|
+
### Sponsored Ad Filtering
|
|
423
|
+
|
|
424
|
+
Booking.com injects paid "native ads" into search results. These are identified and excluded by:
|
|
425
|
+
|
|
426
|
+
1. Detecting `nad_` (native ad tracking) in the hotel card HTML or links
|
|
427
|
+
2. Checking for explicit "Ad", "Sponsored", or "Promoted" labels
|
|
428
|
+
|
|
429
|
+
This ensures you only see organic results, not paid placements.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## Output Format
|
|
434
|
+
|
|
435
|
+
Each hotel result includes:
|
|
436
|
+
|
|
437
|
+
```
|
|
438
|
+
1. Hotel Name
|
|
439
|
+
Price: $XXX per night
|
|
440
|
+
Rating: X.X/10 Rating Text (XXX reviews)
|
|
441
|
+
Location: X.X miles from center
|
|
442
|
+
Amenities: Pool, Free WiFi, Gym, ...
|
|
443
|
+
Match Score: XX
|
|
444
|
+
Why it matches: Near beach, Has WiFi, Has gym, ...
|
|
445
|
+
Book: https://www.booking.com/hotel/...
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## Technical Details
|
|
451
|
+
|
|
452
|
+
### Architecture
|
|
453
|
+
|
|
454
|
+
```
|
|
455
|
+
src/
|
|
456
|
+
├── index.ts # MCP server with tool definitions
|
|
457
|
+
├── browser.ts # Playwright automation & filter mappings
|
|
458
|
+
└── test*.ts # Test scripts
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Dependencies
|
|
462
|
+
|
|
463
|
+
- `@modelcontextprotocol/sdk` - MCP server SDK
|
|
464
|
+
- `playwright` - Browser automation
|
|
465
|
+
- `zod` - Schema validation
|
|
466
|
+
|
|
467
|
+
### Browser Configuration
|
|
468
|
+
|
|
469
|
+
- **Headless Mode**: Runs without visible browser window
|
|
470
|
+
- **Anti-Detection**: Custom user agent and disabled automation flags
|
|
471
|
+
- **Auto-Scrolling**: Loads more results by scrolling the page
|
|
472
|
+
- **Popup Handling**: Automatically dismisses cookie banners and sign-in modals
|
|
473
|
+
|
|
474
|
+
### Filter Code Mappings
|
|
475
|
+
|
|
476
|
+
All Booking.com filter codes are mapped in `browser.ts`:
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
const FILTER_CODES = {
|
|
480
|
+
propertyType: { hotel: "ht_id=204", resort: "ht_id=206", ... },
|
|
481
|
+
hotelfacility: { freeWifi: 107, pool: 433, spa: 54, ... },
|
|
482
|
+
roomfacility: { airConditioning: 11, kitchen: 999, ... },
|
|
483
|
+
popularActivities: { fitness: 11, golf: 12, skiing: 13, ... },
|
|
484
|
+
chaincode: { marriott: 1080, hilton: 1078, ... },
|
|
485
|
+
// ... 20+ filter categories
|
|
486
|
+
};
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## Limitations
|
|
492
|
+
|
|
493
|
+
- **Rate Limiting**: Booking.com may rate-limit or block automated requests
|
|
494
|
+
- **Results Cap**: Returns ~25 results per search (first page + scroll load)
|
|
495
|
+
- **Price Accuracy**: Prices may vary based on availability and timing
|
|
496
|
+
- **Filter Availability**: Some filters may not apply to all destinations
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
## Troubleshooting
|
|
501
|
+
|
|
502
|
+
### "Browser not initialized"
|
|
503
|
+
|
|
504
|
+
Run `npx playwright install chromium` to install the browser.
|
|
505
|
+
|
|
506
|
+
### No results returned
|
|
507
|
+
|
|
508
|
+
- Check that dates are in the future
|
|
509
|
+
- Verify destination spelling
|
|
510
|
+
- Try removing some filters (too restrictive)
|
|
511
|
+
|
|
512
|
+
### Blocked by Booking.com
|
|
513
|
+
|
|
514
|
+
- Wait a few minutes before retrying
|
|
515
|
+
- The server uses anti-detection measures, but excessive requests may trigger blocks
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## License
|
|
520
|
+
|
|
521
|
+
MIT
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export interface HotelSearchParams {
|
|
2
|
+
destination: string;
|
|
3
|
+
checkIn: string;
|
|
4
|
+
checkOut: string;
|
|
5
|
+
guests: number;
|
|
6
|
+
rooms: number;
|
|
7
|
+
}
|
|
8
|
+
export interface HotelFilters {
|
|
9
|
+
minRating?: number;
|
|
10
|
+
maxPrice?: number;
|
|
11
|
+
propertyType?: "hotel" | "apartment" | "resort" | "villa" | "vacation_home" | "hostel" | "bnb" | "guesthouse" | "homestay" | "motel" | "inn" | "lodge" | "chalet" | "campground" | "glamping" | "boat" | "capsule" | "ryokan" | "riad" | "country_house" | "farm_stay";
|
|
12
|
+
starRating?: 1 | 2 | 3 | 4 | 5;
|
|
13
|
+
beachfront?: boolean;
|
|
14
|
+
beachAccess?: boolean;
|
|
15
|
+
oceanView?: boolean;
|
|
16
|
+
freeWifi?: boolean;
|
|
17
|
+
pool?: boolean;
|
|
18
|
+
spa?: boolean;
|
|
19
|
+
fitness?: boolean;
|
|
20
|
+
parking?: boolean;
|
|
21
|
+
freeParking?: boolean;
|
|
22
|
+
restaurant?: boolean;
|
|
23
|
+
bar?: boolean;
|
|
24
|
+
roomService?: boolean;
|
|
25
|
+
airportShuttle?: boolean;
|
|
26
|
+
hotTub?: boolean;
|
|
27
|
+
sauna?: boolean;
|
|
28
|
+
garden?: boolean;
|
|
29
|
+
terrace?: boolean;
|
|
30
|
+
nonSmokingRooms?: boolean;
|
|
31
|
+
familyRooms?: boolean;
|
|
32
|
+
disabledFacilities?: boolean;
|
|
33
|
+
evCharging?: boolean;
|
|
34
|
+
golf?: boolean;
|
|
35
|
+
tennis?: boolean;
|
|
36
|
+
casino?: boolean;
|
|
37
|
+
bbqFacilities?: boolean;
|
|
38
|
+
laundry?: boolean;
|
|
39
|
+
concierge?: boolean;
|
|
40
|
+
currencyExchange?: boolean;
|
|
41
|
+
businessCenter?: boolean;
|
|
42
|
+
meetingRooms?: boolean;
|
|
43
|
+
airConditioning?: boolean;
|
|
44
|
+
kitchen?: boolean;
|
|
45
|
+
balcony?: boolean;
|
|
46
|
+
privatePool?: boolean;
|
|
47
|
+
privateBathroom?: boolean;
|
|
48
|
+
bath?: boolean;
|
|
49
|
+
tv?: boolean;
|
|
50
|
+
coffeemaker?: boolean;
|
|
51
|
+
minibar?: boolean;
|
|
52
|
+
safe?: boolean;
|
|
53
|
+
washingMachine?: boolean;
|
|
54
|
+
soundproofing?: boolean;
|
|
55
|
+
bedType?: "king" | "queen" | "double" | "twin" | "single";
|
|
56
|
+
breakfast?: boolean;
|
|
57
|
+
allInclusive?: boolean;
|
|
58
|
+
selfCatering?: boolean;
|
|
59
|
+
petFriendly?: boolean;
|
|
60
|
+
adultsOnly?: boolean;
|
|
61
|
+
lgbtqFriendly?: boolean;
|
|
62
|
+
freeCancellation?: boolean;
|
|
63
|
+
noPrepayment?: boolean;
|
|
64
|
+
noBookingFee?: boolean;
|
|
65
|
+
sustainabilityCertified?: boolean;
|
|
66
|
+
wheelchairAccessible?: boolean;
|
|
67
|
+
groundFloor?: boolean;
|
|
68
|
+
elevatorAccess?: boolean;
|
|
69
|
+
grabRails?: boolean;
|
|
70
|
+
raisedToilet?: boolean;
|
|
71
|
+
loweredSink?: boolean;
|
|
72
|
+
emergencyCord?: boolean;
|
|
73
|
+
braille?: boolean;
|
|
74
|
+
tactileSigns?: boolean;
|
|
75
|
+
auditoryGuidance?: boolean;
|
|
76
|
+
walkInShower?: boolean;
|
|
77
|
+
rollInShower?: boolean;
|
|
78
|
+
showerChair?: boolean;
|
|
79
|
+
maxDistanceFromCenter?: "half_mile" | "1_mile" | "2_miles";
|
|
80
|
+
snorkeling?: boolean;
|
|
81
|
+
diving?: boolean;
|
|
82
|
+
fishing?: boolean;
|
|
83
|
+
hiking?: boolean;
|
|
84
|
+
cycling?: boolean;
|
|
85
|
+
skiing?: boolean;
|
|
86
|
+
waterSports?: boolean;
|
|
87
|
+
horseRiding?: boolean;
|
|
88
|
+
hotelChain?: "marriott" | "hilton" | "hyatt" | "ihg" | "wyndham" | "best_western" | "accor" | "choice" | "radisson" | "ritz_carlton" | "four_seasons" | "fairmont" | "sheraton" | "westin" | "w_hotels" | "courtyard" | "residence_inn" | "hampton" | "embassy_suites" | "doubletree";
|
|
89
|
+
}
|
|
90
|
+
export interface HotelResult {
|
|
91
|
+
name: string;
|
|
92
|
+
price: number | null;
|
|
93
|
+
priceDisplay: string;
|
|
94
|
+
rating: number | null;
|
|
95
|
+
ratingText: string;
|
|
96
|
+
reviewCount: number | null;
|
|
97
|
+
location: string;
|
|
98
|
+
distanceToCenter: string;
|
|
99
|
+
amenities: string[];
|
|
100
|
+
highlights: string[];
|
|
101
|
+
link: string;
|
|
102
|
+
matchScore?: number;
|
|
103
|
+
matchReasons?: string[];
|
|
104
|
+
}
|
|
105
|
+
export declare class HotelBrowser {
|
|
106
|
+
private browser;
|
|
107
|
+
private page;
|
|
108
|
+
init(headless?: boolean): Promise<void>;
|
|
109
|
+
close(): Promise<void>;
|
|
110
|
+
private buildBookingUrl;
|
|
111
|
+
searchHotels(params: HotelSearchParams, filters?: HotelFilters): Promise<HotelResult[]>;
|
|
112
|
+
private dismissPopups;
|
|
113
|
+
private scrollToLoadMore;
|
|
114
|
+
private extractHotelDetails;
|
|
115
|
+
private scoreAndFilterHotels;
|
|
116
|
+
getHotelDetails(hotelUrl: string): Promise<Record<string, unknown>>;
|
|
117
|
+
takeScreenshot(path: string): Promise<void>;
|
|
118
|
+
getPageContent(): Promise<string>;
|
|
119
|
+
}
|