How it will work: 3 steps
- Follow us on ApifyThe tool is built and waits in the queue for the Apify Store. Apify is the cloud platform where our tools run.
- Paste your input and press StartNo code needed: you fill in a form (the input). It already has a working example. For example:
searchin What to do. Each start is one run. - Download the resultsWhen the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.
This tool is an Apify Actor: a small program that runs on Apify. You can also run it on a schedule, for example every Monday. New to it? Read how it works, step by step and the 8 words you need first.
What it does
This Actor reads public hotel lists and hotel pages on Expedia and Hotels.com. It returns hotels with prices for your dates, ratings, addresses, coordinates and guest reviews.
searchfinds hotels in a place.hotelsreads exact hotels by ID or link.reviewscollects guest reviews for exact hotels.monitorsaves only hotels that are new or whose price changed since the last run.
Good for
- Compare hotel prices in a city for chosen dates.
- Compare one hotel's price across many dates.
- Export guest reviews of your own hotel or of competitors.
- Get a signal when a hotel price changes.
Who uses it
Travel analysts
Compare hotel prices in a city for chosen dates.
Hotel revenue teams
Check your own hotel and rivals across many dates.
Developers
Get hotel data as JSON or CSV for your own tools.
Price
Prices will be shown after release.
Questions
Do I need an account or a login?
No. The tool reads public pages only. You need an Apify account.
Are Expedia and Hotels.com prices the same?
Not always. Run both and compare price by hotelId.
Which prices do I get?
The prices a visitor who is not signed in sees. Member and app prices are not included.
Can I get more than 500 hotels in a city?
Not in one place search. Split the city into areas in destinations, or use filters such as stars.
What happens if a place or hotel does not exist?
A hotel ID that does not exist gives a free not_found row and status NOT_FOUND. For a place name, the site usually picks its nearest match, so check matchedPlace.
How fresh are the prices?
Each row has fetchedAt. The price is what the site showed at that time. The Actor does not promise that the price stays the same or that you can book it.
Details
Step by step on Apify
- Open the Input tab. Keep Expedia in Website (box 1), or choose Hotels.com.
- Keep Lisbon in Destination (box 2), or type your place.
- Open How much to collect (box 3) if you want to change the limit or the dates.
- Click Start.
- Open the Output tab and check the Hotels view (box 5).
Use cases
| Task | Input | You get | Key fields | Next step |
|---|---|---|---|---|
| Compare hotel prices in a city | destination, checkIn, checkOut | Hotel row | name, price, rating, url | CSV export, spreadsheet |
| Compare prices across dates | hotelIds, stays | One hotel row per date pair | hotelId, checkIn, checkOut, price | API, your own database |
| Read guest reviews | mode = reviews, hotelIds | Review row | rating, text, date | CSV export, text analysis |
| Watch price changes | mode = monitor, destination | Changed hotel row | change, previousPrice, price | Schedule, Slack or Notion summary |
| See where a hotel stands in its market | marketSummary, subjectHotel | Market summary row | medianPricePerNight, subjectPricePercentile | Report, spreadsheet |
Tips for better results
- The sites show about 500 hotels per place and dates. Split a city into areas for more.
- Use monitor mode to save only new hotels or hotels with a changed price.
- Run both sites and compare price by hotelId. Do not assume they match.
Limits and good to know
- The sites show about 500 hotels per place and set of dates. Use smaller areas or several places to get more
maxReviewsis at most 2000 per hotel.staysis at most 30 pairs.destinationsandregionIdsare at most 50 each- Prices are what the site shows to a visitor who is not signed in, in the United States. Member and app prices are not included. Taxes are as displayed
- The Actor does not convert currency. It supports USD, GBP, EUR, CAD and AUD
- It does not return hotel descriptions, spoken languages, amenities by category, the guest's name on a review, contact details, flights, cars or Vrbo listings. It does not book
- Sites can change. If a hotel has no price for your dates,
priceisnulland the hotel is still saved
For developers
Sample result
One result from a real test run, in JSON. Real values change from run to run. In Excel or CSV each field is a column.
{
"type": "hotel",
"hotelId": "7369640",
"name": "Meliá Lisboa Aeroporto",
"stars": 4,
"rating": 9.2,
"ratingLabel": "Wonderful",
"reviewsCount": 3098,
"price": 191,
"pricePerNight": 171,
"strikeoutPrice": null,
"priceText": "$191 · $171 nightly · $191 total · Total with taxes and fees",
"priceIncludesTaxes": true,
"currency": "USD",
"address": "Aeroporto Internacional de Lisboa, Rua C, Lisbon, 1700-008",
"city": "Lisbon",
"region": null,
"postalCode": "1700-008",
"countryCode": "PRT",
"lat": 38.770382,
"lng": -9.125218,
"amenities": ["Pool", "Spa", "Free WiFi"],
"url": "https://www.expedia.com/Lisbon-District-Hotels-Melia-Lisboa-Aeroporto.h7369640.Hotel-Information?chkin=2026-12-05&chkout=2026-12-06",
"image": "https://images.trvl-media.com/lodging/8000000/7370000/7369700/7369640/b05af088.jpg?impolicy=resizecrop&ra=fit&rw=455&rh=455",
"neighborhood": "Olivais",
"badges": [],
"site": "expedia",
"host": "www.expedia.com",
"destination": "Lisbon",
"matchedPlace": "Lisbon, Lisbon District, Portugal",
"regionId": "2080",
"checkIn": "2026-12-05",
"checkOut": "2026-12-06",
"adults": 2,
"rooms": 1,
"source": "Expedia",
"fetchedAt": "2026-11-05T05:25:37.426Z"
}Data fields (40)
| Field | Type | Meaning |
|---|---|---|
type | string | hotel, review, market_summary or not_found. Use this column to tell rows apart. |
hotelId | string | The hotel number on Expedia and Hotels.com. |
name | string | Hotel name as published. |
stars | number | Star rating; null when the site shows none. |
rating | number | Guest rating out of 10 on a hotel row, or the guest's score on a review row; null when none is shown. |
ratingLabel | string | The word for the rating, such as Wonderful. |
reviewsCount | integer | Number of guest reviews; null when not shown, 0 only when the site shows 0. |
price | number | Total for the stay as the site displays it; null when no total is shown. No conversion. |
pricePerNight | number | Price per night when the site displays it. |
strikeoutPrice | number | Old crossed-out price when the site shows one. |
priceText | string | The price lines exactly as displayed. |
priceIncludesTaxes | boolean | true when a price line mentions taxes; null when the site does not say. |
currency | string | Currency actually shown by the site for this price. |
address | string | Street address. |
city | string | City. |
region | string | State or province. |
postalCode | string | Postal code. |
countryCode | string | Country code. |
lat | number | Latitude; null when the site has no coordinates. |
lng | number | Longitude; null when the site has no coordinates. |
amenities | array/string | Main amenities as listed. Empty when none are listed. |
url | string | Public hotel page, with the dates when known. |
image | string | Main image link. |
neighborhood | string | Area shown on the search card. |
badges | array/string | Labels shown on the search card, such as VIP Access. |
change | string | Monitor mode: new, priceUp, priceDown, priceAppeared or priceGone. |
previousPrice | number | Monitor mode: the price from the previous run. |
site | string | expedia or hotels. |
host | string | Regional site that was read. |
destination | string | Place as you typed it. |
matchedPlace | string | Place the site really searched for this row. Empty when the row came from a hotel ID or the site did not report a place. |
regionId | string | Region number you gave, or the number the site reports for the searched place. |
checkIn | string | Check-in date of this price. |
checkOut | string | Check-out date of this price. |
adults | integer | Adults per room used for the price. |
rooms | integer | Rooms used for the price. |
roomOffers | array/string | Paid option: rooms with their rate plans. |
policies | array/string | Paid option: hotel policies. |
images | array/string | Paid option: image links. |
ratingBreakdown | object/string | Paid option: counts per score and scores per category. |
Input settings (25)
The main fields of the input form. With the API you send them as JSON.
| Setting | Name in the API | Type | Example value |
|---|---|---|---|
| What to do | mode | string | "search" |
| Website | site | string | "expedia" |
| Destination | destination | string | "Lisbon" |
| More destinations | destinations | array | |
| Region IDs | regionIds | array | |
| Hotel IDs | hotelIds | array | |
| Links | startUrls | array | |
| Check-in date | checkIn | string | "30 days" |
| Check-out date | checkOut | string | "31 days" |
| More dates | stays | array | |
| Adults | adults | integer | 2 |
| Children's ages | childrenAges | array | |
| Rooms | rooms | integer | 1 |
| Currency | currency | string | "USD" |
| Hotels per place and dates | maxItems | integer | 10 |
| Reviews per hotel | maxReviews | integer | |
| Sort hotels by | sortBy | string | "recommended" |
| Star rating | stars | array | |
| Amenities | amenities | array | |
| Property types | propertyTypes | array | |
| Hotel name contains | hotelName | string | |
| Free cancellation only | freeCancellation | boolean | false |
| Breakfast included only | breakfastIncluded | boolean | false |
| Reserve now, pay later only | payLater | boolean | false |
| Minimum price per night | minPrice | number |






