TripAdvisor APItripadvisor.com ↗
Search TripAdvisor locations, list hotels by geo ID, and fetch special offers. Get ratings, review counts, price ranges, and coordinates via 3 structured endpoints.
What is the TripAdvisor API?
The TripAdvisor API exposes 3 endpoints covering location search, hotel listings, and place-level offer details. Use search_location to resolve any city, region, or attraction name into a locationId and geographic coordinates, then pass the resulting geo_id to list_hotels to retrieve paginated hotel records including ratings, review counts, price ranges, phone numbers, and images. Each response uses consistent integer IDs that chain across endpoints.
curl -X GET 'https://api.parse.bot/scraper/f436cbcf-96a4-4f9e-85b0-3acad164fed6/search_location?query=London' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace tripadvisor-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""
TripAdvisor Parse API Client
A practical Python client for the TripAdvisor Scraper API that enables searching locations,
listing hotels with rich metadata, and retrieving place details.
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from typing import Optional, Dict, Any
class ParseClient:
"""Client for interacting with the TripAdvisor Scraper API via Parse."""
def __init__(self, api_key: Optional[str] = None):
"""
Initialize the Parse client.
Args:
api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
"""
self.base_url = "https://api.parse.bot"
self.scraper_id = "f436cbcf-96a4-4f9e-85b0-3acad164fed6"
self.api_key = api_key or os.getenv("PARSE_API_KEY")
if not self.api_key:
raise ValueError(
"API key not provided. Set PARSE_API_KEY environment variable or pass api_key parameter."
)
def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
"""
Make an API call to the Parse scraper.
Args:
endpoint: The endpoint name to call.
method: HTTP method (GET or POST).
**params: Parameters to send with the request.
Returns:
Response data as a dictionary.
Raises:
requests.RequestException: If the API request fails.
"""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json",
}
if method.upper() == "GET":
response = requests.get(url, headers=headers, params=params)
elif method.upper() == "POST":
response = requests.post(url, headers=headers, json=params)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
return response.json()
def search_location(self, query: str) -> Dict[str, Any]:
"""
Search for locations (cities, regions, hotels, attractions) to get their locationId.
Args:
query: Search keyword (e.g., 'London', 'Paris', 'New York City').
Returns:
Dictionary containing results array with location objects.
Each location object contains: locationId, name, placeType, coordinates, etc.
"""
return self._call("search_location", method="GET", query=query)
def list_hotels(
self, geo_id: int, limit: int = 30, offset: int = 0
) -> Dict[str, Any]:
"""
List hotels in a specific location by geoId.
Returns rich data including ratings, address, contact, and pricing.
Args:
geo_id: Location ID from search_location.
limit: Number of results to return (default: 30).
offset: Pagination offset (default: 0).
Returns:
Dictionary containing hotels array with hotel objects.
Each hotel contains location data with name, rating, reviews, and contact info.
"""
return self._call(
"list_hotels", method="GET", geo_id=geo_id, limit=limit, offset=offset
)
def get_place_details(self, location_id: int) -> Dict[str, Any]:
"""
Get special offers and basic metadata for a specific location ID.
Args:
location_id: Specific location/hotel ID.
Returns:
Dictionary containing special offer details for the location.
"""
return self._call(
"get_place_details", method="GET", location_id=location_id
)
def main():
"""Practical workflow: Search for a city, list hotels, and get details for top results."""
# Initialize the client
client = ParseClient()
# Step 1: Search for a destination
print("=" * 70)
print("STEP 1: SEARCHING FOR DESTINATIONS")
print("=" * 70)
query = "London"
print(f"\nSearching for locations matching: '{query}'...\n")
search_results = client.search_location(query)
if not search_results.get("data", {}).get("results"):
print(f"No results found for '{query}'")
return
locations = search_results["data"]["results"]
total = search_results["data"].get("total", len(locations))
print(f"Found {total} location(s):\n")
for idx, location in enumerate(locations[:3], 1):
location_id = location.get("locationId")
name = location.get("name")
place_type = location.get("placeType")
address = location.get("address")
latitude = location.get("latitude", "N/A")
longitude = location.get("longitude", "N/A")
parent_name = location.get("parentName", "N/A")
print(f"{idx}. {name}")
print(f" Type: {place_type} | Location ID: {location_id}")
print(f" Address: {address}")
print(f" Parent: {parent_name}")
print(f" Coordinates: ({latitude}, {longitude})\n")
# Step 2: Get the first city location and list hotels
print("=" * 70)
print("STEP 2: LISTING HOTELS")
print("=" * 70)
# Find a city type location for hotel listing
city_location = None
for location in locations:
if location.get("placeType") == "CITY":
city_location = location
break
if not city_location:
city_location = locations[0]
location_id = city_location.get("locationId")
location_name = city_location.get("name")
print(f"\nFetching hotels in {location_name}...\n")
hotels_response = client.list_hotels(geo_id=int(location_id), limit=5)
if not hotels_response.get("data", {}).get("hotels"):
print(f"No hotels found in {location_name}")
return
hotels = hotels_response["data"]["hotels"]
print(f"Found {hotels_response['data'].get('total', len(hotels))} hotels in {location_name}:\n")
hotel_location_ids = []
for idx, hotel in enumerate(hotels, 1):
hotel_location_id = hotel.get("locationId")
hotel_name = hotel.get("name")
rating = hotel.get("rating", "N/A")
review_count = hotel.get("reviewCount", 0)
address_data = hotel.get("address", {})
street = address_data.get("street", "N/A")
city = address_data.get("city", "N/A")
phone = hotel.get("telephone", "Not available")
price_range = hotel.get("priceRange", "N/A")
latitude = hotel.get("latitude", "N/A")
longitude = hotel.get("longitude", "N/A")
print(f"{idx}. {hotel_name}")
print(f" ⭐ Rating: {rating}/5.0 ({review_count} reviews)")
print(f" Address: {street}, {city}")
print(f" Phone: {phone}")
print(f" Price Range: {price_range}")
print(f" Coordinates: ({latitude}, {longitude})")
print(f" Location ID: {hotel_location_id}\n")
if hotel_location_id:
hotel_location_ids.append(hotel_location_id)
# Step 3: Get special offers for top hotels
print("=" * 70)
print("STEP 3: FETCHING SPECIAL OFFERS")
print("=" * 70)
if hotel_location_ids:
for hotel_id in hotel_location_ids[:3]:
hotel_name = next(
(h.get("name") for h in hotels if h.get("locationId") == hotel_id),
f"Hotel {hotel_id}",
)
print(f"\nFetching special offers for: {hotel_name} (ID: {hotel_id})...")
try:
details = client.get_place_details(int(hotel_id))
offers_data = details.get("data", {}).get(
"BaAggregation_getSpecialOfferDetailsBulk", []
)
if offers_data:
for offer_item in offers_data:
special_offers = offer_item.get("specialOffers", [])
if special_offers:
print(f" ✓ Found {len(special_offers)} special offer(s):")
for offer in special_offers:
offer_id = offer.get("specialOfferId", "N/A")
print(f" - Offer ID: {offer_id}")
else:
print(" ✗ No special offers currently available")
else:
print(" ✗ No offer data available")
except requests.exceptions.RequestException as e:
print(f" ✗ Error fetching details: {e}")
# Summary
print("\n" + "=" * 70)
print("WORKFLOW SUMMARY")
print("=" * 70)
print(f"\nDestination searched: {query}")
print(f"Selected city: {location_name}")
print(f"Hotels retrieved: {len(hotels)}")
print(f"Special offers checked: {min(3, len(hotel_location_ids))} hotels")
print("\nTop hotel recommendations:")
for idx, hotel in enumerate(hotels[:3], 1):
hotel_name = hotel.get("name")
rating = hotel.get("rating", "N/A")
review_count = hotel.get("reviewCount", 0)
print(f" {idx}. {hotel_name}")
print(f" ⭐ {rating}/5.0 ({review_count} reviews)\n")
if __name__ == "__main__":
main()Search for locations (cities, regions, hotels, attractions, restaurants) by keyword to get their locationId and geographic details.
| Param | Type | Description |
|---|---|---|
| queryrequired | string | Search keyword (e.g., 'London', 'Paris', 'New York') |
{
"type": "object",
"fields": {
"total": "integer count of results returned",
"results": "array of location objects with locationId, name, placeType, latitude, longitude, isGeo, address, url, parentName, parentType"
},
"sample": {
"data": {
"total": 1,
"results": [
{
"url": "/Tourism-g186338-London_England-Vacations.html",
"name": "London",
"isGeo": true,
"address": "England, United Kingdom",
"latitude": 51.519241,
"longitude": -0.096654,
"placeType": "CITY",
"locationId": 186338,
"parentName": "United Kingdom",
"parentType": "COUNTRY"
}
]
},
"status": "success"
}
}About the TripAdvisor API
Endpoints and Data Shape
The search_location endpoint accepts a free-text query (e.g., 'London' or 'New York') and returns an array of location objects. Each object includes locationId, name, placeType, latitude, longitude, isGeo, address, url, parentName, and parentType. This is the standard entry point for resolving human-readable names into the integer IDs the other endpoints require.
Hotel Listings
list_hotels takes a required geo_id integer — obtained from search_location or known in advance (e.g., 60763 for New York City, 186338 for London) — and returns up to 30 hotels per page. Pagination is controlled via the offset parameter in multiples of 30, and the response echoes both geo_id and offset for consistency. Each hotel record includes locationId, name, address, latitude, longitude, telephone, image, rating, reviewCount, priceRange, and a direct TripAdvisor url.
Place Details and Special Offers
get_place_details accepts a location_id integer (from either of the other endpoints) and returns special offer data for that property. The response is structured under BaAggregation_getSpecialOfferDetailsBulk, an array of objects containing locationId and a specialOffers array. This endpoint is suited for surfacing current promotions tied to a specific hotel rather than general metadata.
Coverage Notes
All three endpoints return TripAdvisor url fields, making it straightforward to deep-link users to the original listing. placeType in search_location results distinguishes between geo nodes (cities, regions) and point-of-interest types (hotels, attractions, restaurants), which is useful when you need to filter search results before passing IDs downstream.
The TripAdvisor API is a managed, monitored endpoint for tripadvisor.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when tripadvisor.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official tripadvisor.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a hotel price-range comparison tool using
priceRangeandratingfields fromlist_hotels - Resolve destination names to geographic IDs for use in downstream travel itinerary apps via
search_location - Display hotel contact information and direct booking links using
telephoneandurlfields - Surface special hotel promotions by chaining
list_hotelsresults intoget_place_details - Geocode hotels for map-based UIs using
latitudeandlongitudefromlist_hotels - Filter search results by
placeTypeto separate city-level geo nodes from individual attractions or hotels
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does TripAdvisor have an official developer API?+
What does `list_hotels` return, and how does pagination work?+
locationId, name, address, latitude, longitude, telephone, image, rating, reviewCount, priceRange, and url. To paginate, increment the offset parameter by 30 (e.g., 0, 30, 60). The response echoes both geo_id and offset so you can verify the request parameters against the result.Are restaurant or attraction listings available, not just hotels?+
search_location returns results for restaurants, attractions, and other place types alongside hotels — you can identify them via the placeType field. However, dedicated listing endpoints for restaurants or attractions (equivalent to list_hotels) are not currently part of this API. You can fork it on Parse and revise to add those listing endpoints.Does the API return user reviews or review text?+
reviewCount (an integer) and rating per hotel, but do not return individual review text, review titles, or reviewer profiles. You can fork the API on Parse and revise it to add a reviews endpoint that returns per-review content for a given locationId.What is a known limitation of the `get_place_details` endpoint?+
BaAggregation_getSpecialOfferDetailsBulk. It does not return general hotel metadata such as amenities, check-in policies, or room types. If a property has no active special offers, the specialOffers array will be empty.