Skip to content
Hotels.com

Hotels.com price

Hotels.com headline price for one stay window.

POST/v1/ota/hotels
8 credits

One 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

POSThttps://api.scrapercompany.com/v1/ota/hotels

Authenticate 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. For hotels.com/h38766175.Hotel-Information it is 38766175 — digits only, no leading h. The ho… 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 30

    Length of stay. Ignored when check_out is supplied.

  • adultsintegerdefault 2min 1, max 8

    Adults 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 US

    Point-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 US and 585 CAD on CA, an implied 1.11 against a real rate near 1.37. Pick one market per comparison.

    One ofAUCADEEUFRGBIEITNLNZUS

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).

200 response
{
  "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 fields
    • search_parameters.enginestringrequired

      One ofhotels_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 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 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 fields
    • meta.sourcestringrequired

      One ofhotels

    • 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.

StatusMeaningRetry?
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 is a list of problems for schema errors, or a string for semantic checks performed by the endpoint.

{"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

  1. Export your key: export SCRAPERCOMPANY_API_KEY=sk_... (no key yet? request access).
  2. Copy the cURL example above and run it in a terminal.
  3. Or open the interactive playground on api.scrapercompany.com, paste your key and pick this endpoint.

Credits

8 credits per successful call. Failed, blocked and empty results are free. Credit metering is in beta and does not block requests yet.