{
  "openapi": "3.0.1",
  "info": {
    "title": "Google Hotels Prices Scraper & API - OTA Rates, Hotel Details",
    "description": "Google Hotels API: hotel prices by city, hotel name or URL for your dates. One row per hotel: nightly rate, stay total, taxes, deals, availability, rating. Optional OTA rates (Booking.com, Expedia, Agoda, official site): rate parity, price comparison, price tracking. Free: address, phone, amenities.",
    "version": "1.9",
    "x-build-id": "1Ee44hnmvKwvMRZRz"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/kestrel~google-hotels-prices/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-kestrel-google-hotels-prices",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/kestrel~google-hotels-prices/runs": {
      "post": {
        "operationId": "runs-sync-kestrel-google-hotels-prices",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/kestrel~google-hotels-prices/run-sync": {
      "post": {
        "operationId": "run-sync-kestrel-google-hotels-prices",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "checkIn",
          "checkOut"
        ],
        "properties": {
          "queries": {
            "title": "Places",
            "uniqueItems": true,
            "type": "array",
            "description": "Place searches as typed into Google Hotels, e.g. [\"hotels in Lisbon\"], [\"hotels near Times Square\"], [\"5-star hotels Bangkok Sukhumvit\"]. Returns up to maxHotels hotels per place. Write the place exactly and add the country when it is ambiguous (\"hotels in Barcelona Spain\"): Google never fails a place search, a misspelt place is matched to somewhere else and those hotels are billed. After the run check the status row: spread_km (large = wrong or vague place) and each hotel's lat/lng.",
            "items": {
              "type": "string"
            }
          },
          "hotelNames": {
            "title": "Hotels by name",
            "uniqueItems": true,
            "type": "array",
            "description": "Exact hotels by name, no URL needed, e.g. [\"Hyatt Regency Lisbon\", \"Altis Grand Hotel Lisbon\"] (add the city; \"Hotel Artemide, Rome\" with a comma works too). Use for \"what does each booking site charge for hotel X\" and for rate parity. A Google Maps place link works too, and names in Chinese, Japanese, Korean or Thai. A name that matches nothing costs nothing and is reported in a status row; only a hotel whose name matches yours is billed. Filters and maxHotels do not apply to named hotels.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "checkIn": {
            "title": "Check-in",
            "pattern": "^(\\d{4}-\\d{2}-\\d{2}|\\+?\\s*\\d+\\s*(d|days?|w|weeks?|m|months?|y|years?)|today|tomorrow)$",
            "type": "string",
            "description": "Check-in date: \"2026-10-03\" (YYYY-MM-DD), or relative to the day the run starts: \"30 days\", \"6 weeks\", \"tomorrow\". Use relative dates for scheduled runs (\"track prices daily\"): the input never needs editing. A past date is rejected before anything is charged."
          },
          "checkOut": {
            "title": "Check-out",
            "pattern": "^(\\d{4}-\\d{2}-\\d{2}|\\+?\\s*\\d+\\s*(d|days?|w|weeks?|m|months?|y|years?)|today|tomorrow)$",
            "type": "string",
            "description": "Check-out date, after checkIn: \"2026-10-06\", or relative: \"32 days\". Nights = checkOut minus checkIn, so checkIn \"30 days\" + checkOut \"32 days\" = a 2-night stay starting 30 days after each run."
          },
          "adults": {
            "title": "Adults",
            "minimum": 1,
            "maximum": 6,
            "type": "integer",
            "description": "Adults in the room, 1 to 6, e.g. 2 (default 2). Google prices ONE room for the whole party: there is no rooms input, and above 6 adults Google returns no price at all.",
            "default": 2
          },
          "childrenAges": {
            "title": "Children (ages)",
            "type": "array",
            "description": "Ages of the children in the same room, e.g. [5, 9] for two children aged 5 and 9. Empty (default) = no children. The price is for one room holding the adults plus these children.",
            "default": []
          },
          "currency": {
            "title": "Currency",
            "pattern": "^[A-Z]{3}$",
            "minLength": 3,
            "maxLength": 3,
            "type": "string",
            "description": "ISO 4217 code for every price in the run, e.g. \"EUR\". Any currency Google supports: USD, EUR, GBP, JPY, THB, SGD, AUD, AED, … Left empty the actor uses \"USD\". When the user names no currency, pass the destination's (\"EUR\" for Paris).",
            "default": "USD"
          },
          "maxHotels": {
            "title": "Max hotels per place",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Hotels to return per place search and stay, 1 to 200, e.g. 50 (default 20). Filters and sortBy are applied by Google BEFORE this cap: 30 with sortBy \"lowest_price\" = the 30 cheapest matching hotels, and fewer come back only when fewer match. The main cost control: at most maxHotels × $0.004 per place and stay, plus offer rows while includeOffers is true. The largest cities end near 185 hotels.",
            "default": 20
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "relevance",
              "lowest_price",
              "highest_rating",
              "most_reviewed"
            ],
            "type": "string",
            "description": "Google Hotels' own order for place searches: \"relevance\" (default), \"lowest_price\", \"highest_rating\", \"most_reviewed\". Use with maxHotels for \"the 30 cheapest\" or \"the 40 best-rated hotels\". Applied to every stay of a sweep separately. \"lowest_price\" is Google Hotels' own cheapest-first order for the stay.",
            "default": "relevance"
          },
          "includeOffers": {
            "title": "Fetch every source's rates",
            "type": "boolean",
            "description": "true (DEFAULT) = also return each booking site's rate per hotel as offer rows at $0.002 each: about 18 per hotel (up to 36), so about $0.04 per hotel, not $0.004. Set false for one price per hotel, a price calendar or plain price tracking. Keep true for rate parity, OTA comparison, \"which site is cheapest\". The official site is the offer row with official: true, present only when Google lists it. With false the hotel row has the lowest nightly rate but not which site sells it.",
            "default": true
          },
          "offerLevel": {
            "title": "Offer rows per hotel",
            "enum": [
              "sources",
              "rooms"
            ],
            "type": "string",
            "description": "\"sources\" (default) = one offer row per booking site with its lowest rate: about 18 rows per hotel. \"rooms\" = every booking site × room type × rate, with room name, max guests and free-cancellation deadline: about 65 rows per hotel, up to 150 ($0.13–0.30 per hotel). Choose \"rooms\" only when the user asks for room types or cancellation deadlines. Ignored when includeOffers is false.",
            "default": "sources"
          },
          "includeDetails": {
            "title": "Hotel details",
            "type": "boolean",
            "description": "true = each hotel row also gets address, phone, Google Maps place_id, long description, amenities by name (about 120, e.g. \"Wi-Fi (free)\", \"Indoor pool\", \"Parking (extra charge)\"), amenities_unavailable, rating_breakdown (5 to 1 stars), review_aspects (Service, Location, Breakfast… with positive and negative counts), external_ratings (Tripadvisor…) and photos. No extra charge. Default false. Also fills star class, rating and coordinates for hotels given by URL.",
            "default": false
          },
          "sweepDays": {
            "title": "Sweep check-in over N more days",
            "minimum": 0,
            "maximum": 60,
            "type": "integer",
            "description": "0 (default) = only the stay above. N = repeat the same length of stay for each of the next N check-in days, e.g. checkIn \"2026-11-02\", checkOut \"2026-11-04\", sweepDays 13 = 14 two-night stays with check-ins 2 to 15 Nov. Use for a price calendar or \"which day is cheapest\". Every stay is billed as its own rows, so cost × (N + 1): set includeOffers false to keep it low. Maximum 60.",
            "default": 0
          },
          "freeCancellation": {
            "title": "Free cancellation only",
            "type": "boolean",
            "description": "true = only hotels with a free-cancellation rate for the dates. Google then quotes that refundable rate as the hotel's nightly price, and maxPrice applies to it. Default false. Place searches only.",
            "default": false
          },
          "maxPrice": {
            "title": "Maximum price per night",
            "minimum": 0,
            "type": "integer",
            "description": "Highest nightly price in `currency`, e.g. 250. 0 (default) = no maximum. Google applies it to the nightly price it displays (the `nightly` field), before maxHotels, so hotels above it are never returned or billed. Place searches only.",
            "default": 0
          },
          "minRating": {
            "title": "Guest rating",
            "enum": [
              "any",
              "3.5",
              "4.0",
              "4.5"
            ],
            "type": "string",
            "description": "Minimum Google guest rating out of 5, as a string: \"3.5\", \"4.0\" or \"4.5\" (Google offers only these steps). Default \"any\".",
            "default": "any"
          },
          "hotelClass": {
            "title": "Hotel class (stars)",
            "uniqueItems": true,
            "type": "array",
            "description": "Star classes to keep, as strings: [\"4\", \"5\"] = 4-star and 5-star hotels only. Allowed: \"2\", \"3\", \"4\", \"5\". Empty (default) = any class.",
            "items": {
              "type": "string",
              "enum": [
                "2",
                "3",
                "4",
                "5"
              ],
              "enumTitles": [
                "2-star",
                "3-star",
                "4-star",
                "5-star"
              ]
            },
            "default": []
          },
          "amenities": {
            "title": "Amenities",
            "uniqueItems": true,
            "type": "array",
            "description": "Only hotels that have ALL of these, e.g. [\"pool\", \"free_breakfast\"]. Google Hotels' own filters: free_wifi, free_breakfast, restaurant, bar, kid_friendly, pet_friendly, free_parking, parking, ev_charger, room_service, fitness_center, spa, pool (any pool), indoor_pool, outdoor_pool, air_conditioned, wheelchair_accessible, beach_access, all_inclusive. Empty (default) = no filter. To LIST each hotel's amenities use includeDetails.",
            "items": {
              "type": "string",
              "enum": [
                "free_wifi",
                "free_breakfast",
                "restaurant",
                "bar",
                "kid_friendly",
                "pet_friendly",
                "free_parking",
                "parking",
                "ev_charger",
                "room_service",
                "fitness_center",
                "spa",
                "pool",
                "indoor_pool",
                "outdoor_pool",
                "air_conditioned",
                "wheelchair_accessible",
                "beach_access",
                "all_inclusive"
              ],
              "enumTitles": [
                "Free Wi-Fi",
                "Free breakfast",
                "Restaurant",
                "Bar",
                "Kid friendly",
                "Pet friendly",
                "Free parking",
                "Parking",
                "EV charger",
                "Room service",
                "Fitness center",
                "Spa",
                "Pool",
                "Indoor pool",
                "Outdoor pool",
                "Air conditioned",
                "Wheelchair accessible",
                "Beach access",
                "All inclusive"
              ]
            },
            "default": []
          },
          "country": {
            "title": "Market",
            "type": "string",
            "description": "Google market (gl): any 2-letter country code, e.g. \"gb\", \"pt\", \"jp\". Default \"us\". It is the country of the person searching, NOT the destination: keep \"us\" unless the user wants prices as seen from a country. It changes which booking sites are listed (Klook, Traveloka, Wego in Asian markets).",
            "default": "us"
          },
          "language": {
            "title": "Language",
            "type": "string",
            "description": "Google language (hl), e.g. \"en\", \"ja\", \"zh-CN\", \"es\", \"de\". Default \"en\". Sets the language of hotel names (where Google has a translation), room names, class labels and deal notes. Queries and hotelNames may be written in any language.",
            "default": "en"
          },
          "hotels": {
            "title": "Specific hotels",
            "uniqueItems": true,
            "type": "array",
            "description": "Exact hotels by Google Hotels URL (https://www.google.com/travel/hotels/entity/ChkI…) or entity token, e.g. the `entity_id` or `google_url` of rows from an earlier run. Use to price the SAME set of hotels every day: run a place search once, then pass its entity_id values here. Filters and maxHotels do not apply. Add includeDetails for star class, rating and coordinates.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "maxOffersPerHotel": {
            "title": "Max offer rows per hotel",
            "minimum": 0,
            "maximum": 500,
            "type": "integer",
            "description": "0 (default) = every offer row. N = only the N cheapest offer rows per hotel, e.g. 5: a hard cost cap, at most $0.004 + N × $0.002 per hotel. The official-site row is kept only if it is among the N cheapest, so leave 0 for rate parity.",
            "default": 0
          },
          "minPrice": {
            "title": "Minimum price per night",
            "minimum": 0,
            "type": "integer",
            "description": "Lowest nightly price in `currency`, e.g. 80. 0 (default) = no minimum. Applied by Google before maxHotels. Place searches only.",
            "default": 0
          },
          "specialOffers": {
            "title": "Special offers only",
            "type": "boolean",
            "description": "true = only hotels Google marks as a deal for the dates; `deal` carries the note (\"23% less than usual\") and `deal_percent` the number. Default false. Place searches only.",
            "default": false
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Google accepts Apify datacenter proxies for these calls; keep the default. Residential is unnecessary.",
            "default": {
              "useApifyProxy": true
            }
          },
          "sessions": {
            "title": "Parallel proxy sessions",
            "minimum": 1,
            "maximum": 16,
            "type": "integer",
            "description": "Concurrent egress IPs; each is paced at perIp requests per second.",
            "default": 4
          },
          "perIp": {
            "title": "Requests per second per IP",
            "minimum": 0.1,
            "maximum": 2,
            "type": "number",
            "description": "Pace per proxy session. 0.5 is safe; raise carefully.",
            "default": 0.5
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}