Install
openclaw skills install @scavio-ai/scavio-tripadvisorResolve any place or business name to Tripadvisor ids, then pull ranked restaurants, hotels and attractions in a geo, one location in full, and paged review bodies. 4 endpoints, 2 credits each, structured JSON.
openclaw skills install @scavio-ai/scavio-tripadvisorResolve a place or business name to Tripadvisor's own ids, list ranked restaurants, hotels and attractions in a geo, read one location in full, and page through its reviews. All endpoints return structured JSON.
Use this skill when the user asks to:
Get a free API key at https://scavio.dev (50 free credits to get started, no card required):
export SCAVIO_API_KEY=sk_live_your_key
Every request is a POST with a JSON body and:
Authorization: Bearer $SCAVIO_API_KEY
Base URL: https://api.scavio.dev. Every Tripadvisor endpoint costs 2 credits.
| Endpoint | Credits | What it returns |
|---|---|---|
POST /api/v1/tripadvisor/locations | 2 | START HERE. Resolves a place or business NAME to geo_id / location_id |
POST /api/v1/tripadvisor/search | 2 | Restaurants / hotels / attractions in a geo, Tripadvisor-ranked; each row carries the location_id + geo_id pair |
POST /api/v1/tripadvisor/location | 2 | One location in full: rating histogram, sub-ratings, city ranking, price band, cuisines, amenities, contact, photos, and the first page of reviews |
POST /api/v1/tripadvisor/reviews | 2 | A page of reviews: rating, trip date and type, reviewer home town and contribution count, management response |
Start at /locations. Every other endpoint is keyed by ids that exist only inside Tripadvisor's own URLs, so a caller holding a place name has no other entry point.
/tripadvisor/locations with query. Each result carries type, geo_id and location_id.
geo_id for /search. Its location_id is null.geo_id + location_id pair that /location and /reviews take./tripadvisor/search with geo_id and a category (restaurants, hotels, attractions). Or paste a full Tripadvisor listing URL as url instead./tripadvisor/location with location_id (+ geo_id) or a full _Review URL. Page 1 of the reviews already rides along here./tripadvisor/reviews only to page past the first page./search renders 30 locations per page. A page beyond the last is a 404, not an empty result./reviews page size depends on the family - 15 for restaurants, 10 for hotels and attractions - so category must match the location's own type on any page past the first, or you will page in the wrong stride.review_id when concatenating./locations and /location do not page. On /locations, limit only sizes the single response (1-20, default 12); it is not a page parameter./locations)| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | required | Place or business name (1-120 chars) |
limit | integer | 12 | 1-20. Sizes this response only; not pagination |
/search)| Parameter | Type | Default | Description |
|---|---|---|---|
geo_id | string | one of | Accepts 30196, g30196, or a URL carrying one |
url | string | one of | Full tripadvisor.com listing URL (country sites and subdomains accepted) |
category | string | restaurants | restaurants, hotels, attractions |
page | integer | -- | 1-based, 30 locations per page |
geo_id or url is required.
/location)| Parameter | Type | Default | Description |
|---|---|---|---|
location_id | string | one of | Accepts 1899234, d1899234, or a full _Review URL |
url | string | one of | Full Tripadvisor location URL |
geo_id | string | -- | Required alongside a bare d-id |
category | string | restaurants | restaurants, hotels, attractions |
location_id or url is required; a bare d-id additionally needs a geo.
/reviews)| Parameter | Type | Default | Description |
|---|---|---|---|
location_id | string | one of | Location id, or send url instead |
url | string | one of | Full Tripadvisor location URL |
geo_id | string | -- | Geo the location belongs to |
category | string | restaurants | Must match the location's own type - it sets the page stride |
page | integer | -- | 1-based. 15/page restaurants, 10/page hotels and attractions. Past the last page is a 404 |
import os, requests
BASE = "https://api.scavio.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['SCAVIO_API_KEY']}"}
# 1. ALWAYS START HERE - a name is not an id
places = requests.post(f"{BASE}/api/v1/tripadvisor/locations", headers=HEADERS,
json={"query": "Austin, Texas"}).json()
geo = next(r for r in places["data"]["results"] if r["type"] == "GEO")
# 2. Ranked restaurants in that geo
listing = requests.post(f"{BASE}/api/v1/tripadvisor/search", headers=HEADERS,
json={"geo_id": geo["geo_id"], "category": "restaurants"}).json()
row = listing["data"]["results"][0]
# 3. One venue in full - page 1 of its reviews comes along for free
venue = requests.post(f"{BASE}/api/v1/tripadvisor/location", headers=HEADERS,
json={"location_id": row["location_id"], "geo_id": row["geo_id"],
"category": "restaurants"}).json()
# 4. Page PAST that first page - keep category in step with the venue type
more = requests.post(f"{BASE}/api/v1/tripadvisor/reviews", headers=HEADERS,
json={"location_id": row["location_id"], "geo_id": row["geo_id"],
"category": "restaurants", "page": 2}).json()
Concatenating review pages, de-duplicated on review_id:
def review_pages(location_id, geo_id, category="restaurants", pages=(2, 3, 4)):
"""2 credits per page. Page 1 already came with /location."""
seen, out = set(), []
for page in pages:
data = requests.post(f"{BASE}/api/v1/tripadvisor/reviews", headers=HEADERS,
json={"location_id": location_id, "geo_id": geo_id,
"category": category, "page": page}).json()["data"]
for r in data["reviews"]:
if r["review_id"] not in seen: # pages overlap at the boundary
seen.add(r["review_id"])
out.append(r)
return out
Every response uses the envelope { data, response_time, credits_used, credits_remaining }. Key data fields:
query, count, results[] (pos, type (GEO or a business type), name, geo_id, location_id (null on a GEO row), url, latitude, longitude, category).geo_id, category, location, url, page, count, breadcrumbs, results[] (pos, location_id, geo_id, type, name, rank, url, image, rating, review_count, price_range, price, cuisines, street_address, city, region, postal_code, country, address, latitude, longitude, phone, hours, menu_url, accepts_reservations, description, ranking, review_snippet, travelers_choice, sponsored).location_id, geo_id, type, url, name, description, rating, review_count, rating_distribution, subratings, ranking, ranking_position, ranking_total, ranking_category, price_range, cuisines, meal_types, special_diets, street_address, city, region, postal_code, country, address, latitude, longitude, phone, website, menu_url, hours, hours_text, open_now, amenities, features, image, images, photo_count, travelers_choice, breadcrumbs, reviews[] (page 1).location_id, geo_id, type, url, name, rating, review_count, rating_distribution, offset, count, reviews[] (pos, review_id, url, title, text, rating, published_date, trip_date, trip_type, author, author_url, author_location, author_contributions, helpful_votes, owner_response, owner_response_date, owner_response_from).{
"data": {
"query": "Austin, Texas",
"count": 10,
"results": [
{
"pos": 1,
"type": "GEO",
"name": "Austin, Texas, United States",
"geo_id": "30196",
"location_id": null,
"url": "https://www.tripadvisor.com/Tourism-g30196-Austin_Texas-Vacations.html",
"latitude": 30.267223,
"longitude": -97.742546,
"category": "Destinations"
}
]
},
"credits_used": 2,
"credits_remaining": 998
}
geo_id or location_id. Resolve the name with /locations first; ids only exist inside Tripadvisor's URLs./reviews with page: 1 after /location - you already have that page, and the repeat costs another 2 credits.category matched to the venue's own type when paging reviews. A restaurant pages in 15s and a hotel in 10s; a mismatch silently skips or repeats reviews.review_id when you concatenate pages - the boundary review can repeat.400 means an invalid or missing parameter - neither geo_id nor url on search, neither location_id nor url on location/reviews, a bare d-id with no geo, or a category outside the enum. Fix and retry.401 means the API key is invalid or missing. Check SCAVIO_API_KEY.404 means the id does not exist or the page is past the last one. Tripadvisor answers an unknown location id with a billed 200 city listing that the API restates as a 404 - re-resolve the name with /locations rather than retrying the id.429 means rate or usage limit exceeded. Wait before retrying. See https://scavio.dev/docs/rate-limits.502 / 503 mean upstream is temporarily unavailable - wait a few seconds and retry, up to a few times./locations returns nothing useful, try the fuller place name ("Austin, Texas" rather than "Austin").SCAVIO_API_KEY is not set, prompt the user to export it before continuing.pip install scavio
from scavio import ScavioClient
client = ScavioClient() # reads SCAVIO_API_KEY
places = client.tripadvisor.locations("Austin, Texas")
geo = next(r for r in places["data"]["results"] if r["type"] == "GEO")
listing = client.tripadvisor.search(geo_id=geo["geo_id"], category="restaurants")
row = listing["data"]["results"][0]
venue = client.tripadvisor.location(location_id=row["location_id"], geo_id=row["geo_id"])
more = client.tripadvisor.reviews(location_id=row["location_id"], geo_id=row["geo_id"], page=2)
npm install scavio
import { Scavio } from "scavio";
const client = new Scavio(); // reads SCAVIO_API_KEY
const places = await client.tripadvisor.locations({ query: "Austin, Texas" });
const listing = await client.tripadvisor.search({ geo_id: "30196", category: "restaurants" });