Hotels.com price
Hotels.com headline price for one stay window.
/v1/ota/hotelsOne small request. price_per_night is the sticky bar's lead price, as it always was; on the US and DE points-of-sale that is the stay total including taxes and fees, so price_per_night_is says which it is and total/nightly carry the labelled figures. An unbookable stay is available: false with Hotels.com's own unavailable_reason, billed like any other answer; only a reply with nothing in it is free.
Request
https://api.scrapercompany.com/v1/ota/hotelsAuthenticate with your API key in the x-api-key header (see Authentication).
Body
JSON object. Unknown fields are rejected with 422.
- property_idstringrequiredmin length 1
Numeric id returned by
POST /v1/ota/hotels/search. Forhotels.com/h38766175.Hotel-Informationit is38766175— digits only, no leadingh. Theho…number in a page URL is a legacy id the rate endpoints do not price. - check_instring (date)required
First night of the stay,
YYYY-MM-DD. - check_outstring (date) | null
Departure date. An alternative to
nights— if both are given, this wins. - nightsintegerdefault
1min 1, max 30Length of stay. Ignored when
check_outis supplied. - adultsintegerdefault
2min 1, max 8Adults in the room. Two is the hotel default; pass one for a hostel, which is priced per bed. Any value from 1 to 8 is accepted.
- marketstringdefault
USPoint-of-sale, which is how currency is selected — there is no currency field. Prices are not comparable across markets: the display basis differs, so the same night reads 527 USD on
USand 585 CAD onCA, an implied 1.11 against a real rate near 1.37. Pick one market per comparison.One of
AUCADEEUFRGBIEITNLNZUS
Example request
curl -X POST "https://api.scrapercompany.com/v1/ota/hotels" \
-H "x-api-key: $SCRAPERCOMPANY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"property_id": "12570",
"check_in": "2026-11-30",
"nights": 1,
"market": "US"
}'Response
200 — Headline price for one window, measured on www.hotels.com. `price_per_night` is the sticky bar's lead price as before; here (`price_per_night_is: stay_total`) that is the stay total, and `nightly` is Hotels.com's own nightly figure before taxes and fees. `currency` is what the point-of-sale actually priced in. Metered responses carry x-credits-charged and x-credits-remaining headers (see credit headers).
{
"search_parameters": {
"engine": "hotels_property",
"property_id": "12570",
"check_in_date": "2029-04-10",
"check_out_date": "2029-04-11",
"adults": 2,
"market": "US",
"currency": "USD"
},
"property": {
"property_id": "12570",
"price_per_night": 475,
"price_per_night_is": "stay_total",
"total": 475,
"nightly": 374,
"lead_text": "$475",
"total_text": "$475",
"nightly_text": "$374 nightly",
"currency": "USD",
"currency_verified": true,
"available": true,
"provenance": {
"schema_version": 1,
"observation_id": "rateobs_0123456789abcdef0123456789abcdef",
"collection_id": "ratecol_0123456789abcdef0123456789abcdef",
"observed_at": "2026-08-07T01:23:45.678Z",
"source": "hotels_com",
"source_kind": "ota_offer",
"collector": "scrapingme.ota.hotels",
"source_property_id": "12570",
"requested_market": "US",
"requested_currency": "USD",
"returned_currency": "USD",
"egress_mode": "direct",
"price_basis": "stay_headline",
"derivation": "parsed_display_price"
}
},
"meta": {
"source": "hotels",
"nights": 1,
"wire_bytes": 6066,
"egress_mode": "direct",
"elapsed_s": 2.35,
"comparable_across_markets": false
}
}Response fields
Fields marked required are always present; others appear when they apply.
- search_parametersobjectrequired
Show 7 child fieldsHide child fields
- search_parameters.enginestringrequired
One of
hotels_property - search_parameters.property_idstringrequired
- search_parameters.check_in_datestring (date)required
- search_parameters.check_out_datestring (date)required
- search_parameters.adultsintegerrequired
- search_parameters.marketstringrequired
- search_parameters.currencystringrequired
The market's currency.
- propertyobjectrequired
Show 6 child fieldsHide child fields
- property.property_idstringrequired
- property.price_per_nightnumber | nullrequired
- property.currencystringrequired
Currency the point-of-sale actually priced in.
- property.currency_verifiedbooleanrequired
- property.availablebooleanrequired
- property.provenanceobjectrequired
Where, when and how one normalized price was observed.
Show 15 child fieldsHide child fields
- property.provenance.schema_versionintegerrequired
Provenance schema version (currently 1).
- property.provenance.observation_idstringrequired
Deterministic id of this price observation (
rateobs_...). - property.provenance.collection_idstringrequired
Id shared by every price from one upstream fetch (
ratecol_...). - property.provenance.observed_atstringrequired
UTC observation time, ISO-8601.
- property.provenance.sourcestringrequired
Upstream source, e.g.
google_hotels_calendar. - property.provenance.source_kindstringrequired
Kind of source, e.g.
calendar,offer,ota_calendar,official. - property.provenance.collectorstringrequired
Identifier of the collector that produced the price.
- property.provenance.source_property_idstringrequired
Property identifier at the source.
- property.provenance.requested_marketstring | nullrequired
- property.provenance.requested_currencystring | nullrequired
- property.provenance.returned_currencystring | nullrequired
- property.provenance.egress_modestringrequired
How the request reached the source, e.g.
direct. - property.provenance.price_basisstringrequired
What the price represents, e.g.
room_base_before_taxes_and_fees. - property.provenance.derivationstringrequired
How the figure was derived, e.g.
normalized_upstream. - property.provenance.upstream_rate_idstring | nullrequired
Source-native rate/room id when available.
- metaobjectrequired
Show 6 child fieldsHide child fields
- meta.sourcestringrequired
One of
hotels - meta.collection_idstringrequired
- meta.observed_atstringrequired
- meta.nightsintegerrequired
- meta.elapsed_snumberrequired
- meta.comparable_across_marketsbooleanrequired
Always false.
Errors
Errors return a JSON body with a detail field. Failed requests are not charged. See Errors for the full list and retry advice.
| Status | Meaning | Retry? |
|---|---|---|
401Unauthorized | Missing or invalid API key. {"detail":"missing or invalid API key"} | No, fix the request |
402Payment Required | Not enough credits for this request. Only returned once credit enforcement is switched on; during the beta metering runs in shadow mode and never blocks. {"detail":"insufficient credits: this request costs 5, 0 available. Credits renew 2026-11-01."} | No, fix the request |
422Unprocessable Content | Request validation failed. {"detail":[{"loc":["body","name"],"msg":"Field required","type":"missing"}]} | No, fix the request |
429Too Many Requests | Too many requests: the key's requests-per-minute limit was exceeded, or (once credit enforcement is on) the plan's concurrent-request limit. No rate-limit or Retry-After headers are sent; back off and retry. {"detail":"rate limit 60/min exceeded"} | Yes, with backoff |
502Bad Gateway | The upstream source failed, blocked the request or returned an unusable answer. Safe to retry later; failed requests are not charged. {"detail":"RuntimeError"} | Yes, with backoff |
503Service Unavailable | Temporarily unavailable: a dependency of this endpoint is down, or the upstream source changed its contract. Retry later. {"detail":"database unavailable: OperationalError"} | Yes, with backoff |
Try it
- Export your key:
export SCRAPERCOMPANY_API_KEY=sk_...(no key yet? request access). - Copy the cURL example above and run it in a terminal.
- Or open the interactive playground on api.scrapercompany.com, paste your key and pick this endpoint.