DEV Community

Cover image for How to Scrape TripAdvisor Reviews in 2026 (Python + a No-Code Shortcut)
Factden
Factden

Posted on

How to Scrape TripAdvisor Reviews in 2026 (Python + a No-Code Shortcut)

Here is the thing most people hit when they try to scrape TripAdvisor reviews: the official TripAdvisor Content API returns only 3 reviews per location. Three. For a hotel with eight thousand reviews, that is not a dataset, that is a teaser. And it is gated behind an approval process, with no owner responses and no subratings.

This guide covers what you can pull from a TripAdvisor review, why the DIY route is fiddly, working Python, a no-code shortcut, and a plain comparison. If you want the deeper reference, there is a full guide to scraping TripAdvisor reviews too.

What you can pull from a review

Per review you can get:

  • The overall star rating (1 to 5), the review title, and the full review text with its language
  • Per-review subratings: cleanliness, service, value, location, rooms, sleep quality, where the reviewer left them
  • Dates: the published date and the travel date, plus helpful votes
  • Owner / management responses, with responder name and date
  • Reviewer profile: username, home location, contribution count
  • An LLM-ready markdown block per review

And this works across all three TripAdvisor place types: hotels, restaurants, and attractions. Every run also returns a place record with property details (rating, structured city ranking, price range, hotel class, amenities), TripAdvisor's official category subratings, and its own AI review summary.

Why scraping TripAdvisor is hard

  1. The official API caps at 3 reviews. So for anything at scale, scraping the public data is the route, and there is no owner-response or subrating data in that API anyway.
  2. Three different place types, three URL formats. Hotels use Hotel_Review, restaurants use Restaurant_Review, attractions use Attraction_Review. A scraper built for one type misses the others.
  3. Reviews are paginated and loaded dynamically, not sitting in the initial HTML, so a plain request gets you a shell.
  4. Bot protection and rate limits on top.

So the work is handling each place type, paging through every review, pulling the nested subratings and owner responses, and staying unblocked, on repeat.

Three ways to get the data

DIY Python TripAdvisor Hotel Reviews API (actor) Official Content API
Reviews per location All, if you build paging All Only 3
Setup time Hours to days ~30 seconds Approval required
Hotels + restaurants + attractions Build per type One run Limited
Subratings + owner responses Extra parsing Yes No
Property details + AI summary Separate scrape Same run No
Cost Proxies + eng time Pay-per-result Gated
Best for One-off Scheduled, at scale Not much

Option A: DIY in Python

A plain request to a hotel page returns a JavaScript shell, not the reviews:

import httpx

url = "https://www.tripadvisor.com/Hotel_Review-g187497-d1465497-Reviews-W_Barcelona-Barcelona_Catalonia.html"
r = httpx.get(url, headers={"User-Agent": "Mozilla/5.0"})
print("reviewText" in r.text)   # usually False; reviews load separately, paginated
Enter fullscreen mode Exit fullscreen mode

To get the real data you page through every review, normalize hotels vs restaurants vs attractions, dig the subratings and owner responses out of nested structures, and keep requests unblocked. Fine for one place, a lot of moving parts for a portfolio or a whole city.

Option B: the no-code / API shortcut

When you want clean rows, the TripAdvisor Hotel Reviews API on Apify takes any TripAdvisor URL (or a bare location ID), and returns structured JSON: every review plus the place record. No login, no proxy setup, it handles the blocking for you.

from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("factden/tripadvisor-hotel-reviews-api").call(run_input={
    "mode": "reviews",
    "startUrls": [
        {"url": "https://www.tripadvisor.com/Hotel_Review-g187497-d1465497-Reviews-W_Barcelona-Barcelona_Catalonia.html"}
    ],
    "locationIds": ["1465497"],
    "maxReviews": 500,
    "reviewLanguages": ["all"],
    "minRating": 1,
    "maxRating": 5,
})
for review in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(review["rating"], review["title"], review["text"][:60])
Enter fullscreen mode Exit fullscreen mode

Paste URLs or bare location IDs (the d-number in the URL), mix them freely. Set maxReviews high for all of them. Filter by reviewLanguages, bound the star range with minRating / maxRating, and window the dates with fromDate / toDate (both YYYY-MM-DD).

Don't know the places yet? Switch to Discover mode and search a whole city:

run = client.actor("factden/tripadvisor-hotel-reviews-api").call(run_input={
    "mode": "discover",
    "searchTerms": ["Barcelona"],
    "placeTypes": ["hotels"],
    "maxPlaces": 20,
    "discoveryDepth": "quick",
})
Enter fullscreen mode Exit fullscreen mode

That returns a list of the city's places with full details. Take the returned location IDs back into Reviews mode to pull their reviews.

Track reputation over time

The fromDate filter is the one to know if you care about reputation monitoring. Set a Schedule in Apify, point fromDate at your last run, and each run brings back only the new reviews and rating changes since then. That is how teams track new reviews and ratings over time without re-pulling the whole history every time, one cheap incremental pull on a cron.

What comes back: 16 fields per review

Group Fields
Core placeId, placeType, placeName, reviewId, url
Rating rating (1 to 5), title, subratings (cleanliness, service, value, location, rooms, sleep quality)
Text text, language
Dates & signals publishedDate, travelDate, helpfulVotes
Owner ownerResponse (responder, text, date)
Reviewer user (username, userLocation, contributions)
AI-ready markdownContent

A trimmed sample row:

{
  "placeId": 1465497,
  "placeType": "hotel",
  "placeName": "W Barcelona",
  "reviewId": "1070232616",
  "rating": 5,
  "title": "Incredible stay",
  "text": "The rooftop and the service were exceptional...",
  "publishedDate": "2026-07-26T23:11:20-04:00",
  "travelDate": "2026-07",
  "helpfulVotes": 3,
  "subratings": [{ "name": "Service", "value": 5 }, { "name": "Location", "value": 5 }],
  "ownerResponse": { "responder": "GM W Barcelona", "text": "Thank you...", "publishedDate": "2026-07-28" },
  "user": { "username": "traveler_bcn", "userLocation": "London, UK", "contributions": 42 },
  "markdownContent": "# Incredible stay, W Barcelona\n**Rating:** 5/5 ..."
}
Enter fullscreen mode Exit fullscreen mode

Every run also emits a place record per place: name, geo, overall rating, structured city ranking, price range, hotel class, amenities, TripAdvisor's official category subratings, and its AI review summary. Full field list and snippets are in the GitHub repo.

Grab a free sample dataset

Want to see the data first? There is a free TripAdvisor sample (CSV/JSON) here: factden.com/sample-tripadvisor. Load it into pandas and the ratings and subratings are ready to plot.

FAQ

Is scraping TripAdvisor legal? The reviews are publicly visible. As with any scraping, check TripAdvisor's Terms of Service and your local rules (including GDPR/CCPA for the pseudonymous reviewer fields), and use the data responsibly.

Is there an official TripAdvisor reviews API? Yes, the Content API, but it is gated and returns only 3 reviews per location, with no owner responses or subratings. Scraping the public data is the practical route.

Can I scrape restaurants and attractions too, not just hotels? Yes. One actor covers hotels, restaurants, and attractions, with the same schema, tagged by placeType.

Are ratings on the 5-star scale? Yes, TripAdvisor uses 1 to 5 stars, and that is what rating returns, with per-review subratings on the same scale.

Can I monitor a place for new reviews on a schedule? Yes. Set a Schedule and use fromDate so each run only returns reviews posted since the last pull, ideal for ongoing reputation monitoring.

How do I stop getting blocked? The actor handles it for you and reads the data directly. Plain requests get a JavaScript shell, not the reviews.

Related

Questions, or a field you wish it extracted? Drop a comment.

Top comments (0)