Blog/Local data
10 min read

TripAdvisor API: 2,000 Results, 30 a Page, One Id

A search for Kyoto hotels returned 30 typed rows out of 2,000, every one carrying a rating and a place id. What the typed fields are actually for.

TripAdvisor API: 2,000 Results, 30 a Page, One Id

Copy this line to your agent to pull a city's hotels with ratings.

set up https://monid.ai/SKILL.md and use litescrape /tripadvisor/search for hotels in a city

We searched TripAdvisor for hotels in Kyoto on 2026-10-02. The response reported 2,000 total results, handed back 30 of them, and every single row carried a rating and a place id. It also quietly included one attraction in a hotel search, and it ordered the list by something that is not the rating. Both are fine once you know, and both will skew a ranking if you do not. This guide runs through Monid, the OpenRouter for agent tools.

What does the TripAdvisor API return?

A page of typed entities, with the ids and the next call included.

The query

q is free text up to 500 characters and is the only required field. locale sets the language, tripadvisor_domain switches to a localised site, geo_id restricts to a TripAdvisor geography, and lat plus lon search around a point instead.

The row

Ten fields, and three of them are the ones that matter:

{ "position": 1,
  "position_in_page": 1,
  "place_id": "…",
  "title": "Four Seasons Hotel Kyoto",
  "location": "Kyoto, Kyoto Prefecture",
  "type": "ACCOMMODATION",
  "detail_type": "Hotel",
  "rating": 4.5,
  "description": "…",
  "link": "…" }

type and detail_type are the typed classification. place_id is the key you carry to any follow-up call. rating was present on all thirty rows, which is less common than it sounds in local data.

The counts

"search_information": { "total_results": 2000, "results_on_page": 30 }

Two thousand matches, thirty per page. A full sweep of one city is 67 calls, and that is the number to budget with rather than the one you hope for.

The pagination is done for you

Instead of a cursor you have to assemble, the response includes a complete next-call object: the endpoint and the query parameters, ready to send. Fewer places to get the paging wrong.

📖 See also Yelp API: The Ads Above the Results Had 5 Reviews

Why did a hotel search return an attraction?

Because free text is a search, not a filter, and the API tells you which is which.

The type distribution across our thirty rows:

29   ACCOMMODATION / Hotel
 1   ATTRACTION / Attraction

We asked for "hotels in Kyoto" and got one attraction. TripAdvisor matched on relevance to the phrase, and something in that entity's text was relevant enough.

This is the good failure mode

Compare it to what you get from a scraped results page, where an attraction and a hotel look identical and you are left guessing from the title. Here the row says type: "ATTRACTION" and you drop it in one line:

const hotels = rows.filter(r => r.type === "ACCOMMODATION");

Use place_type rather than cleaning up afterwards

The endpoint takes a place_type parameter, which defaults to all. Setting it does the filtering before you are billed for rows you throw away. Free-text filtering is for when you do not know the shape of what you want; place_type is for when you do.

The general rule this illustrates

A typed field in the response is worth more than a better query string. You cannot phrase your way out of a relevance engine, and you can always filter a labelled result. When comparing local-data endpoints, look for which ones return a type at all, which is the same reason the Yelp endpoint's separate ads array is worth more than its sort parameter.

Is the default order the ranking you want?

Almost certainly not, and the ratings make it obvious.

rank  rating  hotel
  1    4.5    Four Seasons Hotel Kyoto
  2    4.4    Hotel Granvia Kyoto
  3    4.4    Hotel Okura Kyoto
  4    4.2    Kyoto Century Hotel
  5    4.6    Hotel Kanra Kyoto
  8    4.7    The Ritz-Carlton, Kyoto

The highest-rated hotel in the top eight is at rank 8. The fourth-ranked has the lowest rating on the page. The order is TripAdvisor's own relevance and popularity blend, and the endpoint passes it through without re-sorting.

Why this matters more than it looks

If you take the first ten rows and present them as "the best hotels in Kyoto", you have published TripAdvisor's relevance ranking under your own name and called it quality. Our sample had a 4.7 sitting below a 4.2.

Sort client-side on the field you mean. Rating was present on every row, so this costs nothing:

rows.sort((a, b) => b.rating - a.rating);

What rating does not carry here

A rating with no review count behind it is half a number. A 5.0 from three guests and a 4.5 from four thousand are not comparable, and the search row does not carry the count. For a serious ranking you need the volume as well, which means a follow-up call per property and a real cost decision, exactly the trade-off we measured on the Yelp review endpoint.

How do you pull a city's hotels?

For agents

Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:

set up https://monid.ai/SKILL.md

It learns the whole discover, inspect, run workflow itself. More in the agent quickstart.

For humans

npm install -g @monid-ai/cli
monid keys add -k <your-api-key> -l main

Step 1, search with the type pinned

monid run -p litescrape -e /tripadvisor/search \
  --query '{"q":"hotels in Kyoto","locale":"en-US","place_type":"accommodation"}'

Pinning the type up front is cheaper than filtering afterwards, because you are billed per call and a call full of attractions is a wasted one.

Step 2, read the counts before you loop

const { total_results, results_on_page } = res.search_information;
const pages = Math.ceil(total_results / results_on_page);  // 67 for Kyoto

Decide whether you want all 67 before you start. For most jobs the first two pages answer the question.

Step 3, follow the supplied next call

The response hands you a ready-made pagination.next with the endpoint and parameters filled in. Send it rather than building your own offset, which is one fewer thing to get wrong when the page size changes.

Step 4, keep place_id as your key

Titles drift, get renamed and collide between cities. place_id is stable and is what any follow-up call will want, the same deduplication discipline as keying property data on a zpid rather than on an address in the Zillow guide.

Give this to your agent

$Set up https://monid.ai/SKILL.md, and then use Monid to pull the first three pages of hotels in Kyoto, drop anything that is not accommodation, sort by rating, and give me a table with name, rating and link.

📖 See also Automate Google Maps Business Listings Into a Table

Which endpoint should I use for which job?

EndpointWhat it doesInputReturnsLatency we sawBilling
litescrape/tripadvisor/searchTravel entities in a placeq, locale, place_type, geo_id30 typed rows with ratings and idsUnder 10 sPer call
litescrape/yelp/searchLocal businessesfind_loc, find_descOrganic and ads in separate arraysAround 10 sPer call
litescrape/google/shoppingWhat things costA queryProducts with pricesAround 6 sPer call
zillow/search_homes_for_saleProperty around the arealocationListings and countsUnder 6 sPer call

Every row was verified with monid inspect on 2026-10-02 and the latency column is what we actually waited. Billing shape is given rather than figures, because shape drives design and current numbers live on monid.ai/tools.

The first two rows cover overlapping ground and answer different questions. TripAdvisor knows travel entities, hotels, attractions and restaurants as a traveller sees them, with the ratings of people who travelled there. Yelp knows local businesses as a resident sees them. For a hotel, use the first. For the coffee shop next to it, use the second. Running both and merging is a reasonable third option, and place_id from either will not match the other, so keep them in separate columns.

When should you not use this?

Four cases.

You need live prices or availability. This is a discovery surface. Rates, dates and inventory come from a booking system, and nothing in these rows will tell you whether a room is free tonight.

You are sweeping many cities. 67 calls for one city's hotels, before any follow-up. Ten cities is 670 calls for the listings alone. Narrow by geo_id or by coordinates, or accept the first two pages, which is usually what the question deserves.

You need review text. The search row carries a rating and a description, not the reviews. That is a separate retrieval and a separate cost.

You are republishing the ratings as your own. A rating is TripAdvisor's aggregate of their users' writing. Using it internally to rank candidates is ordinary. Presenting it on your own site as your score, or stripping the attribution, is a different act and one their terms have opinions about.

And the disclosure: we resell this endpoint. The most useful thing in this post is that you should re-sort the results yourself, which costs nothing and is a one-line fix whoever you buy the data from.

Conclusion

One search for Kyoto hotels on 2026-10-02 returned 30 rows out of 2,000, every one with a rating and a stable place_id, plus a ready-made next-call object for paging. That is a clean shape, and two things in it will bite a ranking that trusts the defaults.

The list came back in TripAdvisor's own relevance order, not by rating. The highest-rated property in the top eight sat at rank 8, and the fourth-ranked had the lowest rating on the page. If you present the first ten rows as the best hotels in a city, you are publishing someone else's relevance blend under your own name. Sorting is one line and the field is already there.

The search also returned one attraction among 29 hotels, which is what free text does. The response labels it, so dropping it is a filter rather than a guess, and setting place_type on the way in avoids paying for the row at all. A typed field in the response beats a cleverer query string every time.

Free next step: run monid inspect -p litescrape -e /tripadvisor/search, make one call, and print the type and rating columns next to the position. The two mismatches show up immediately. Start at monid.ai.

FAQ

How do you get the reviews rather than the listings?

The search endpoint returns a rating and a short description, not review text, so reviews are a separate retrieval. Plan the cost shape before you start: a search is one call for thirty properties, and reading reviews is at least one call per property on top. For a ranking job you usually do not need the text at all, because the rating plus a review count is enough to order a shortlist. For understanding why a property is rated the way it is, you need the writing, and the efficient pattern is to narrow to a handful of properties first and only then fetch. The same trade-off, measured with numbers, is in the Yelp guide linked above.

What is place_id actually good for?

It is the stable identity of an entity, which is the thing titles are not. Hotel names change, get rebranded, and repeat across cities, so keying your own store on the title guarantees duplicates and misses. place_id survives all of that and is what any follow-up call against this provider expects. Two warnings. It is provider-specific: a TripAdvisor place id means nothing to Yelp or Google, so if you merge sources you need your own identity layer and a column per provider. And it identifies the entity, not the listing, so a property that leaves and rejoins the platform may or may not return with the same id, which is worth sampling before you depend on it for long-term tracking.

Does it work outside the US and in other languages?

Yes, and there are two separate knobs. locale sets the response language, taking either a language code like en or a language-country pair like en-US. tripadvisor_domain switches to a localised TripAdvisor hostname entirely, which changes not just the language but which properties and which reviews are surfaced, because the regional sites differ. Our Kyoto search ran against the US domain in English and returned Japanese properties with English titles, which is the common case and usually what you want for an English-language product. If your users are local, set both, and sample the results, because the two domains do not return the same ordering.

What can you do with the ratings?

Internal use is the comfortable zone: ranking a shortlist, screening suppliers, building a model, comparing one city against another. The rating is an aggregate computed by TripAdvisor from writing their users contributed, and both the computation and the writing belong to other parties. Publishing those numbers on a customer-facing page as though they were your own assessment is where it gets uncomfortable, and stripping the attribution is worse. The safer construction, and the more useful one, is to compute something of your own from the data and show that, citing the source. If the output faces customers or feeds a commercial listing, read the terms and take advice rather than taking a blog post's word for it.

Last updated October 2026.

tripadvisor apitripadvisor scraperhotel data apitravel dataattraction data