{"id":"494ef907-ca60-4fee-be25-45c18abeec3e","entityType":"agent","slug":"clawhub-chrischall-tripadvisor-api","name":"tripadvisor-api","canonicalUrl":"https://www.xpersona.co/agent/clawhub-chrischall-tripadvisor-api","canonicalPath":"/agent/clawhub-chrischall-tripadvisor-api","generatedAt":"2026-10-10T10:42:57.681Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:12:02.871Z","emptyReason":null},"description":"Query TripAdvisor location data (search, nearby, details, photos, reviews) straight from a shell with curl against the Terra REST API (terra.tripadvisor.com), instead of running the tripadvisor-mcp server — plus a no-API-key fallback that reads a location's public page through the fpx browser bridge. Use when you want TripAdvisor data without the MCP, in a script, or on a machine where the MCP isn't installed. Triggers on \"check TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search, details, photos, reviews\", or any TripAdvisor data request that should hit the API directly.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.6K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:tripadvisor-api","sourceUrl":"https://clawhub.ai/chrischall/tripadvisor-api","homepage":"https://clawhub.ai/chrischall/skills/tripadvisor-api","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/chrischall/tripadvisor-api","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/chrischall/skills/tripadvisor-api","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":64,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"tripadvisor-api technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:12:02.871Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:12:02.871Z","emptyReason":null},"stars":null,"forks":null,"downloads":1566,"packageName":null,"latestVersion":"1.1.8","tractionLabel":"1.6K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:12:02.849Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T08:12:02.871Z","lastCrawledAt":"2026-10-10T08:12:02.849Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T08:12:02.849Z","lastVerifiedAt":null,"highlights":[{"version":"1.1.8","createdAt":"2026-10-09T23:27:09.793Z","changelog":"- Removed the redundant skill-card.md file for a cleaner repo. - No changes to functionality or documentation.","fileCount":5,"zipByteSize":8649},{"version":"1.1.7","createdAt":"2026-10-07T13:42:19.067Z","changelog":"- Removed the redundant skill-card.md file. - No changes to code or user-facing functionality.","fileCount":5,"zipByteSize":8625},{"version":"1.1.6","createdAt":"2026-10-05T02:52:02.320Z","changelog":"- Removed the file skill-card.md. - No changes to behavior or endpoints; documentation and functionality remain unchanged.","fileCount":5,"zipByteSize":8617},{"version":"1.1.5","createdAt":"2026-10-03T01:42:58.184Z","changelog":"- Removed the file skill-card.md for simplification. - No functional changes; all API usage and documentation remain unchanged. - The skill continues to provide TripAdvisor data access via curl and supports no-API-key fallback using fpx. - Update is maintenance-only, affecting project metadata and file structure.","fileCount":5,"zipByteSize":8643},{"version":"1.1.4","createdAt":"2026-09-28T13:55:34.686Z","changelog":"- Updated documentation to reference ContextMint Bridge as the new fetchproxy extension, with source and releases linked. - Clarified pairing instructions and replaced Transporter mentions with ContextMint Bridge throughout the SKILL.md. - Removed obsolete skill-card.md file.","fileCount":5,"zipByteSize":8713},{"version":"1.1.3","createdAt":"2026-09-25T15:51:38.670Z","changelog":"- Removed the sample skill card file (skill-card.md) from the repository. - No changes to code or core documentation; only auxiliary documentation updated.","fileCount":5,"zipByteSize":8429},{"version":"1.1.2","createdAt":"2026-09-23T21:45:19.663Z","changelog":"- Removed the file skill-card.md. - No user-facing functional changes. This update is a minor cleanup.","fileCount":5,"zipByteSize":8647},{"version":"1.1.1","createdAt":"2026-09-23T15:42:04.039Z","changelog":"- Removed the file skill-card.md (no functionality or documentation changes). - No changes to usage, functionality, or setup for users.","fileCount":5,"zipByteSize":8721}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:tripadvisor-api","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:tripadvisor-api` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/chrischall/tripadvisor-api before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T10:42:57.678Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-tripadvisor-api/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T08:12:02.871Z","emptyReason":null},"readme":"Skill: tripadvisor-api\n\nOwner: chrischall\n\nSummary: Query TripAdvisor location data (search, nearby, details, photos, reviews) straight from a shell with curl against the Terra REST API (terra.tripadvisor.com), instead of running the tripadvisor-mcp server — plus a no-API-key fallback that reads a location's public page through the fpx browser bridge. Use when you want TripAdvisor data without the MCP, in a script, or on a machine where the MCP isn't installed. Triggers on \"check TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search, details, photos, reviews\", or any TripAdvisor data request that should hit the API directly.\n\nTags: latest:1.1.8\n\nVersion history:\n\nv1.1.8 | 2026-10-09T23:27:09.793Z | auto\n\n- Removed the redundant skill-card.md file for a cleaner repo.\n- No changes to functionality or documentation.\n\nv1.1.7 | 2026-10-07T13:42:19.067Z | auto\n\n- Removed the redundant skill-card.md file.\n- No changes to code or user-facing functionality.\n\nv1.1.6 | 2026-10-05T02:52:02.320Z | auto\n\n- Removed the file skill-card.md.\n- No changes to behavior or endpoints; documentation and functionality remain unchanged.\n\nv1.1.5 | 2026-10-03T01:42:58.184Z | auto\n\n- Removed the file skill-card.md for simplification.\n- No functional changes; all API usage and documentation remain unchanged.\n- The skill continues to provide TripAdvisor data access via curl and supports no-API-key fallback using fpx.\n- Update is maintenance-only, affecting project metadata and file structure.\n\nv1.1.4 | 2026-09-28T13:55:34.686Z | auto\n\n- Updated documentation to reference ContextMint Bridge as the new fetchproxy extension, with source and releases linked.\n- Clarified pairing instructions and replaced Transporter mentions with ContextMint Bridge throughout the SKILL.md.\n- Removed obsolete skill-card.md file.\n\nv1.1.3 | 2026-09-25T15:51:38.670Z | auto\n\n- Removed the sample skill card file (skill-card.md) from the repository.\n- No changes to code or core documentation; only auxiliary documentation updated.\n\nv1.1.2 | 2026-09-23T21:45:19.663Z | auto\n\n- Removed the file skill-card.md.\n- No user-facing functional changes. This update is a minor cleanup.\n\nv1.1.1 | 2026-09-23T15:42:04.039Z | auto\n\n- Removed the file skill-card.md (no functionality or documentation changes).\n- No changes to usage, functionality, or setup for users.\n\nv1.1.0 | 2026-09-20T02:50:28.362Z | auto\n\n- Removed the unnecessary skill-card.md file from the repository.\n- No changes to core functionality or documentation. This is a cleanup release.\n\nv1.0.0 | 2026-09-19T11:19:20.117Z | auto\n\n- Removed the skill-card.md file.\n- No functional or interface changes; skill usage and documentation remain unchanged.\n\nv0.6.4 | 2026-09-15T19:24:49.690Z | auto\n\n- Removed the skill-card.md file (no longer included in the project).\n- No functional or API changes; documentation and usage remains the same.\n\nv0.6.3 | 2026-09-14T14:09:19.217Z | auto\n\n- Removed the skill-card.md file.\n- No user-facing changes to API or documentation content.\n\nv0.6.2 | 2026-09-10T17:51:56.726Z | auto\n\n- Removed the file skill-card.md.\n- No changes to skill functionality or documentation content.\n- This release is a minor cleanup, removing unused or redundant files.\n\nv0.6.1 | 2026-09-09T21:16:20.727Z | auto\n\n- Removed the file skill-card.md.\n- No changes to skill logic or documentation beyond file removal.\n\nv0.6.0 | 2026-09-08T00:35:51.267Z | auto\n\n- Removed the file: skill-card.md\n- No other user-facing or API changes.\n\nv0.5.1 | 2026-09-05T00:51:55.074Z | auto\n\n- Removed the sample file skill-card.md for a cleaner repository.\n- No changes to API, features, or skill behavior.\n\nv0.5.0 | 2026-09-04T22:22:12.530Z | auto\n\n- Removed the skill-card.md file.\n- No changes to functionality or documentation.\n\nv0.4.0 | 2026-08-29T13:54:23.833Z | auto\n\n- Removed the skill-card.md file.  \n- No functional or API changes; only documentation/assets affected.\n- No user-facing features were modified in this release.\n\nv0.3.5 | 2026-08-28T21:07:55.397Z | auto\n\n- Removed the sample file skill-card.md.\n- No other changes to functionality or documentation.\n\nv0.3.4 | 2026-08-28T11:35:28.218Z | auto\n\n- Removed the skill-card.md file.\n- No functional changes to API, logic, or documentation.\n\nv0.3.3 | 2026-08-06T00:43:14.607Z | auto\n\n- Removed the file skill-card.md.\n- No changes to functionality or documentation content.\n\nv0.3.2 | 2026-07-30T12:54:00.450Z | auto\n\n- Removed the sample file skill-card.md.\n- No functional changes to the skill code or documentation.\n\nv0.3.1 | 2026-07-27T02:56:44.149Z | auto\n\n- New skill to query TripAdvisor location data (search, details, photos, reviews) directly from the shell using the Terra REST API via curl.\n- Supports both API-key-protected Terra endpoints and a no-API-key fallback using the fpx browser bridge for public page data.\n- Designed as an alternative to running tripadvisor-mcp, useful for scripting and environments without MCP installed.\n- Includes clear setup, usage guidance, and error handling details for both Terra API and browser bridge fallback.\n- Triggers on \"check TripAdvisor\" and any TripAdvisor data request to hit the API directly.\n\nArchive index:\n\nArchive v1.1.8: 5 files, 8649 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2170b), SKILL.md (5814b), _meta.json (134b)\n\nFile v1.1.8:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in ContextMint Bridge\n```\n\nRequires the **ContextMint Bridge** extension\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases) —\nChrome: load the chrome zip unpacked; Safari isn't available yet, so use Chrome for now)\nwith an open `www.tripadvisor.com` tab. ContextMint Bridge is the fetchproxy extension renamed, same maintainer; source at https://github.com/nullnet-app/contextmint-bridge — build it or verify the release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.8:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.8\",\n  \"publishedAt\": 1791588429793\n}\n\nFile v1.1.8:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id calls.\n\n## 4. Location details (`ta_get_location_details` / `src/tools/location.ts`)\n\n`GET /locations/{id}` — path `id` (int), **plural** `/locations/{id}` (the\ndocs' llms.txt index shows the singular form; that 404s). Optional\n`locale` (repeated).\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675\" | jq '{\n  id, geo, name: (.names[] | select(.primary) | .value),\n  rating: .traveler_ratings.overall, address: .addresses[0],\n  phone: .phone_numbers[0].value, url: .urls.tripadvisor.main\n}'\n```\n\nResponse: the full `Location` object directly (not wrapped in `data`) —\n`names`/`descriptions`/`addresses` are language-tagged arrays; the primary\nentry has `\"primary\": true`.\n\n## 5. Location photos (`ta_get_location_photos` / `src/tools/location.ts`)\n\n`GET /locations/{id}/photos` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/photos?size=10\" \\\n  | jq '[.data[] | {id, url: .photo.original_size_url, w: .photo.original_width, h: .photo.original_height}]'\n```\n\nResponse: `{\"data\": [{\"id\",\"location_id\",\"photo\": {\"key\",\"original_size_url\",\"original_height\",\"original_width\",\"media_type\"}, \"publish_ts\", \"source\": {\"name\"}, \"user\"}], \"pagination\": {...}}`.\n\n## 6. Location reviews (`ta_get_location_reviews` / `src/tools/location.ts`)\n\n`GET /locations/{id}/reviews` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/reviews?size=10\" | jq '.data'\n```\n\nResponse: `{\"data\": [...review objects...], \"pagination\": {...}}`.\n\n---\n\n## Error bodies\n\n- `400` — `{\"type\",\"title\",\"status\",\"detail\",\"field_errors\": [{\"field\",\"message\"}],\"trace_id\"}`.\n- `401`/`403` — `{\"Message\": \"...\"}` (a legacy-vs-Terra key mismatch reads\n  as an AWS-gateway \"explicit deny\" message on the legacy endpoint).\n- `404` — `{\"message\": \"Not Found\"}`.\n- `429` — QPS (10) or daily quota (10,000) exceeded on Discover.\n\nFile v1.1.8:references/web-fallback.md\n\n# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/typeahead`,\n  `/Search?q=`) is a dead end (empty body, 404, needs auth, or a hydrated\n  SPA shell with no SSR data). **Resolve a `locationId` via the Terra\n  `GET /locations/search` endpoint** (`references/terra-endpoints.md` §1),\n  or take it from a TripAdvisor URL, then use this fallback for detail.\n- Individual review **text** is not in the ld+json (no `Review` schema\n  block, no Apollo/redux store) — only the aggregate rating/count. Use the\n  Terra `GET /locations/{id}/reviews` endpoint for review text.\n- If the fetched body isn't valid HTML with an ld+json block (a\n  bot-challenge interstitial slipped through), re-open/refresh the\n  `www.tripadvisor.com` tab and retry.\n\nFile v1.1.8:skill-card.md\n\n## Description:\n\nHelps agents query TripAdvisor locations, photos, and reviews through the read-only Terra API, with a browser-assisted fallback for public location details.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to look up TripAdvisor locations, nearby places, details, photos, and reviews without running an MCP server. Public location details can also be retrieved through a paired browser when an API key is unavailable.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: An API key may be exposed if printed from a local environment file or included in shared command output.\n\nMitigation: Set TRIPADVISOR_API_KEY using a secret manager or shell environment, and avoid printing or sharing the key.\n\nRisk: Pairing the browser fetch bridge grants access to requests through the signed-in TripAdvisor tab.\n\nMitigation: Approve pairing only for the intended TripAdvisor profile and use the bridge only when needed.\n\n## Reference(s):\n\n- [TripAdvisor API skill release](https://clawhub.ai/chrischall/skills/tripadvisor-api)\n- [TripAdvisor developer portal](https://www.tripadvisor.com/developers)\n- [Terra endpoint recipes](artifact/references/terra-endpoints.md)\n- [Browser fallback guide](artifact/references/web-fallback.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Text, JSON, Shell commands, Guidance]\n\n**Output Format:** [Markdown guidance with shell examples and JSON location data]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only location data; review text requires the API rather than the browser fallback.]\n\n## Skill Version(s):\n\n1.1.8 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.7: 5 files, 8625 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2058b), SKILL.md (5814b), _meta.json (134b)\n\nFile v1.1.7:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in ContextMint Bridge\n```\n\nRequires the **ContextMint Bridge** extension\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases) —\nChrome: load the chrome zip unpacked; Safari isn't available yet, so use Chrome for now)\nwith an open `www.tripadvisor.com` tab. ContextMint Bridge is the fetchproxy extension renamed, same maintainer; source at https://github.com/nullnet-app/contextmint-bridge — build it or verify the release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.7:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.7\",\n  \"publishedAt\": 1791380539067\n}\n\nFile v1.1.7:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id calls.\n\n## 4. Location details (`ta_get_location_details` / `src/tools/location.ts`)\n\n`GET /locations/{id}` — path `id` (int), **plural** `/locations/{id}` (the\ndocs' llms.txt index shows the singular form; that 404s). Optional\n`locale` (repeated).\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675\" | jq '{\n  id, geo, name: (.names[] | select(.primary) | .value),\n  rating: .traveler_ratings.overall, address: .addresses[0],\n  phone: .phone_numbers[0].value, url: .urls.tripadvisor.main\n}'\n```\n\nResponse: the full `Location` object directly (not wrapped in `data`) —\n`names`/`descriptions`/`addresses` are language-tagged arrays; the primary\nentry has `\"primary\": true`.\n\n## 5. Location photos (`ta_get_location_photos` / `src/tools/location.ts`)\n\n`GET /locations/{id}/photos` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/photos?size=10\" \\\n  | jq '[.data[] | {id, url: .photo.original_size_url, w: .photo.original_width, h: .photo.original_height}]'\n```\n\nResponse: `{\"data\": [{\"id\",\"location_id\",\"photo\": {\"key\",\"original_size_url\",\"original_height\",\"original_width\",\"media_type\"}, \"publish_ts\", \"source\": {\"name\"}, \"user\"}], \"pagination\": {...}}`.\n\n## 6. Location reviews (`ta_get_location_reviews` / `src/tools/location.ts`)\n\n`GET /locations/{id}/reviews` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/reviews?size=10\" | jq '.data'\n```\n\nResponse: `{\"data\": [...review objects...], \"pagination\": {...}}`.\n\n---\n\n## Error bodies\n\n- `400` — `{\"type\",\"title\",\"status\",\"detail\",\"field_errors\": [{\"field\",\"message\"}],\"trace_id\"}`.\n- `401`/`403` — `{\"Message\": \"...\"}` (a legacy-vs-Terra key mismatch reads\n  as an AWS-gateway \"explicit deny\" message on the legacy endpoint).\n- `404` — `{\"message\": \"Not Found\"}`.\n- `429` — QPS (10) or daily quota (10,000) exceeded on Discover.\n\nFile v1.1.7:references/web-fallback.md\n\n# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/typeahead`,\n  `/Search?q=`) is a dead end (empty body, 404, needs auth, or a hydrated\n  SPA shell with no SSR data). **Resolve a `locationId` via the Terra\n  `GET /locations/search` endpoint** (`references/terra-endpoints.md` §1),\n  or take it from a TripAdvisor URL, then use this fallback for detail.\n- Individual review **text** is not in the ld+json (no `Review` schema\n  block, no Apollo/redux store) — only the aggregate rating/count. Use the\n  Terra `GET /locations/{id}/reviews` endpoint for review text.\n- If the fetched body isn't valid HTML with an ld+json block (a\n  bot-challenge interstitial slipped through), re-open/refresh the\n  `www.tripadvisor.com` tab and retry.\n\nFile v1.1.7:skill-card.md\n\n## Description:\n\nGuides agents in retrieving TripAdvisor location search results, nearby places, details, photos, and reviews through the Terra API, with a browser-based fallback for public location details.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to look up TripAdvisor places and retrieve location details, photos, and reviews from a shell without running an MCP server. A signed-in browser can provide basic public location details when no API key is available.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: An API key may be exposed when copied from local files or printed in command output.\n\nMitigation: Use a preconfigured environment variable or secret manager; do not grep or print real API keys.\n\nRisk: The browser fallback uses a paired extension with access to a signed-in TripAdvisor session.\n\nMitigation: Enable the fallback only if you trust the extension and use a dedicated browser profile.\n\n## Reference(s):\n\n- [Terra API endpoint recipes](references/terra-endpoints.md)\n- [Browser fallback instructions](references/web-fallback.md)\n- [TripAdvisor developer portal](https://www.tripadvisor.com/developers)\n- [ContextMint Bridge source](https://github.com/nullnet-app/contextmint-bridge)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Guidance, Code]\n\n**Output Format:** [Markdown with shell commands and JSON examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only location lookups; the browser fallback returns aggregate ratings but not individual review text.]\n\n## Skill Version(s):\n\n1.1.7 (source: server-resolved release)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.6: 5 files, 8617 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2106b), SKILL.md (5814b), _meta.json (134b)\n\nFile v1.1.6:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in ContextMint Bridge\n```\n\nRequires the **ContextMint Bridge** extension\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases) —\nChrome: load the chrome zip unpacked; Safari isn't available yet, so use Chrome for now)\nwith an open `www.tripadvisor.com` tab. ContextMint Bridge is the fetchproxy extension renamed, same maintainer; source at https://github.com/nullnet-app/contextmint-bridge — build it or verify the release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.6:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.6\",\n  \"publishedAt\": 1791168722320\n}\n\nFile v1.1.6:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id calls.\n\n## 4. Location details (`ta_get_location_details` / `src/tools/location.ts`)\n\n`GET /locations/{id}` — path `id` (int), **plural** `/locations/{id}` (the\ndocs' llms.txt index shows the singular form; that 404s). Optional\n`locale` (repeated).\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675\" | jq '{\n  id, geo, name: (.names[] | select(.primary) | .value),\n  rating: .traveler_ratings.overall, address: .addresses[0],\n  phone: .phone_numbers[0].value, url: .urls.tripadvisor.main\n}'\n```\n\nResponse: the full `Location` object directly (not wrapped in `data`) —\n`names`/`descriptions`/`addresses` are language-tagged arrays; the primary\nentry has `\"primary\": true`.\n\n## 5. Location photos (`ta_get_location_photos` / `src/tools/location.ts`)\n\n`GET /locations/{id}/photos` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/photos?size=10\" \\\n  | jq '[.data[] | {id, url: .photo.original_size_url, w: .photo.original_width, h: .photo.original_height}]'\n```\n\nResponse: `{\"data\": [{\"id\",\"location_id\",\"photo\": {\"key\",\"original_size_url\",\"original_height\",\"original_width\",\"media_type\"}, \"publish_ts\", \"source\": {\"name\"}, \"user\"}], \"pagination\": {...}}`.\n\n## 6. Location reviews (`ta_get_location_reviews` / `src/tools/location.ts`)\n\n`GET /locations/{id}/reviews` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/reviews?size=10\" | jq '.data'\n```\n\nResponse: `{\"data\": [...review objects...], \"pagination\": {...}}`.\n\n---\n\n## Error bodies\n\n- `400` — `{\"type\",\"title\",\"status\",\"detail\",\"field_errors\": [{\"field\",\"message\"}],\"trace_id\"}`.\n- `401`/`403` — `{\"Message\": \"...\"}` (a legacy-vs-Terra key mismatch reads\n  as an AWS-gateway \"explicit deny\" message on the legacy endpoint).\n- `404` — `{\"message\": \"Not Found\"}`.\n- `429` — QPS (10) or daily quota (10,000) exceeded on Discover.\n\nFile v1.1.6:references/web-fallback.md\n\n# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/typeahead`,\n  `/Search?q=`) is a dead end (empty body, 404, needs auth, or a hydrated\n  SPA shell with no SSR data). **Resolve a `locationId` via the Terra\n  `GET /locations/search` endpoint** (`references/terra-endpoints.md` §1),\n  or take it from a TripAdvisor URL, then use this fallback for detail.\n- Individual review **text** is not in the ld+json (no `Review` schema\n  block, no Apollo/redux store) — only the aggregate rating/count. Use the\n  Terra `GET /locations/{id}/reviews` endpoint for review text.\n- If the fetched body isn't valid HTML with an ld+json block (a\n  bot-challenge interstitial slipped through), re-open/refresh the\n  `www.tripadvisor.com` tab and retry.\n\nFile v1.1.6:skill-card.md\n\n## Description:\n\nHelps agents look up TripAdvisor locations, photos, and reviews through the read-only Terra API, with a browser-based fallback for basic location details.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nTravel-planning agents and developers use this skill to search for places and retrieve TripAdvisor location details, photos, and reviews without running an MCP server. A paired browser can retrieve basic public location details when an API key is unavailable.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The agent handles a TripAdvisor API key, and reading local .env files can expose credentials.\n\nMitigation: Provide the key through a secure environment or secrets mechanism rather than searching .env files; do not include the key in responses.\n\nRisk: The optional browser fallback uses a paired bridge tied to a TripAdvisor browser session.\n\nMitigation: Use the fallback only after reviewing the bridge's access and approving the pairing; prefer the API when a key is available.\n\n## Reference(s):\n\n- [Terra API endpoint recipes](references/terra-endpoints.md)\n- [Browser fallback guidance](references/web-fallback.md)\n- [TripAdvisor developer portal](https://www.tripadvisor.com/developers)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Shell commands, Guidance]\n\n**Output Format:** [Markdown with shell commands and JSON excerpts]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only lookups; browser fallback returns aggregate ratings but not individual review text.]\n\n## Skill Version(s):\n\n1.1.6 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.5: 5 files, 8643 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2148b), SKILL.md (5814b), _meta.json (134b)\n\nFile v1.1.5:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in ContextMint Bridge\n```\n\nRequires the **ContextMint Bridge** extension\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases) —\nChrome: load the chrome zip unpacked; Safari isn't available yet, so use Chrome for now)\nwith an open `www.tripadvisor.com` tab. ContextMint Bridge is the fetchproxy extension renamed, same maintainer; source at https://github.com/nullnet-app/contextmint-bridge — build it or verify the release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.5:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.5\",\n  \"publishedAt\": 1790991778184\n}\n\nFile v1.1.5:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id calls.\n\n## 4. Location details (`ta_get_location_details` / `src/tools/location.ts`)\n\n`GET /locations/{id}` — path `id` (int), **plural** `/locations/{id}` (the\ndocs' llms.txt index shows the singular form; that 404s). Optional\n`locale` (repeated).\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675\" | jq '{\n  id, geo, name: (.names[] | select(.primary) | .value),\n  rating: .traveler_ratings.overall, address: .addresses[0],\n  phone: .phone_numbers[0].value, url: .urls.tripadvisor.main\n}'\n```\n\nResponse: the full `Location` object directly (not wrapped in `data`) —\n`names`/`descriptions`/`addresses` are language-tagged arrays; the primary\nentry has `\"primary\": true`.\n\n## 5. Location photos (`ta_get_location_photos` / `src/tools/location.ts`)\n\n`GET /locations/{id}/photos` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/photos?size=10\" \\\n  | jq '[.data[] | {id, url: .photo.original_size_url, w: .photo.original_width, h: .photo.original_height}]'\n```\n\nResponse: `{\"data\": [{\"id\",\"location_id\",\"photo\": {\"key\",\"original_size_url\",\"original_height\",\"original_width\",\"media_type\"}, \"publish_ts\", \"source\": {\"name\"}, \"user\"}], \"pagination\": {...}}`.\n\n## 6. Location reviews (`ta_get_location_reviews` / `src/tools/location.ts`)\n\n`GET /locations/{id}/reviews` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/reviews?size=10\" | jq '.data'\n```\n\nResponse: `{\"data\": [...review objects...], \"pagination\": {...}}`.\n\n---\n\n## Error bodies\n\n- `400` — `{\"type\",\"title\",\"status\",\"detail\",\"field_errors\": [{\"field\",\"message\"}],\"trace_id\"}`.\n- `401`/`403` — `{\"Message\": \"...\"}` (a legacy-vs-Terra key mismatch reads\n  as an AWS-gateway \"explicit deny\" message on the legacy endpoint).\n- `404` — `{\"message\": \"Not Found\"}`.\n- `429` — QPS (10) or daily quota (10,000) exceeded on Discover.\n\nFile v1.1.5:references/web-fallback.md\n\n# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/typeahead`,\n  `/Search?q=`) is a dead end (empty body, 404, needs auth, or a hydrated\n  SPA shell with no SSR data). **Resolve a `locationId` via the Terra\n  `GET /locations/search` endpoint** (`references/terra-endpoints.md` §1),\n  or take it from a TripAdvisor URL, then use this fallback for detail.\n- Individual review **text** is not in the ld+json (no `Review` schema\n  block, no Apollo/redux store) — only the aggregate rating/count. Use the\n  Terra `GET /locations/{id}/reviews` endpoint for review text.\n- If the fetched body isn't valid HTML with an ld+json block (a\n  bot-challenge interstitial slipped through), re-open/refresh the\n  `www.tripadvisor.com` tab and retry.\n\nFile v1.1.5:skill-card.md\n\n## Description:\n\nGuides agents to retrieve TripAdvisor location search results, details, photos, and reviews through the Terra API, with a browser-based fallback for public location details.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to look up TripAdvisor locations, nearby places, photos, and reviews without an MCP server. A paired browser can retrieve limited public location details when an API key is unavailable.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: A TripAdvisor API key may be exposed when copied or printed from a local .env file.\n\nMitigation: Provide TRIPADVISOR_API_KEY through normal secret management and avoid printing it in terminal output.\n\nRisk: The optional browser fallback requires pairing a browser bridge and saving fetched page HTML locally.\n\nMitigation: Use the fallback only if comfortable pairing the bridge for tripadvisor.com and writing fetched HTML to /tmp.\n\n## Reference(s):\n\n- [ClawHub tripadvisor-api release](https://clawhub.ai/chrischall/skills/tripadvisor-api)\n- [TripAdvisor developer portal](https://www.tripadvisor.com/developers)\n- [Terra endpoint recipes](references/terra-endpoints.md)\n- [Browser fallback guide](references/web-fallback.md)\n- [ContextMint Bridge source and releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Shell commands, Configuration instructions]\n\n**Output Format:** [Markdown with shell and JSON examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [API lookups return read-only location data; browser fallback provides limited public location details.]\n\n## Skill Version(s):\n\n1.1.5 (source: ClawHub release)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.4: 5 files, 8713 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2384b), SKILL.md (5814b), _meta.json (134b)\n\nFile v1.1.4:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in ContextMint Bridge\n```\n\nRequires the **ContextMint Bridge** extension\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases) —\nChrome: load the chrome zip unpacked; Safari isn't available yet, so use Chrome for now)\nwith an open `www.tripadvisor.com` tab. ContextMint Bridge is the fetchproxy extension renamed, same maintainer; source at https://github.com/nullnet-app/contextmint-bridge — build it or verify the release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.4:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.4\",\n  \"publishedAt\": 1790603734686\n}\n\nFile v1.1.4:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id calls.\n\n## 4. Location details (`ta_get_location_details` / `src/tools/location.ts`)\n\n`GET /locations/{id}` — path `id` (int), **plural** `/locations/{id}` (the\ndocs' llms.txt index shows the singular form; that 404s). Optional\n`locale` (repeated).\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675\" | jq '{\n  id, geo, name: (.names[] | select(.primary) | .value),\n  rating: .traveler_ratings.overall, address: .addresses[0],\n  phone: .phone_numbers[0].value, url: .urls.tripadvisor.main\n}'\n```\n\nResponse: the full `Location` object directly (not wrapped in `data`) —\n`names`/`descriptions`/`addresses` are language-tagged arrays; the primary\nentry has `\"primary\": true`.\n\n## 5. Location photos (`ta_get_location_photos` / `src/tools/location.ts`)\n\n`GET /locations/{id}/photos` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/photos?size=10\" \\\n  | jq '[.data[] | {id, url: .photo.original_size_url, w: .photo.original_width, h: .photo.original_height}]'\n```\n\nResponse: `{\"data\": [{\"id\",\"location_id\",\"photo\": {\"key\",\"original_size_url\",\"original_height\",\"original_width\",\"media_type\"}, \"publish_ts\", \"source\": {\"name\"}, \"user\"}], \"pagination\": {...}}`.\n\n## 6. Location reviews (`ta_get_location_reviews` / `src/tools/location.ts`)\n\n`GET /locations/{id}/reviews` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/reviews?size=10\" | jq '.data'\n```\n\nResponse: `{\"data\": [...review objects...], \"pagination\": {...}}`.\n\n---\n\n## Error bodies\n\n- `400` — `{\"type\",\"title\",\"status\",\"detail\",\"field_errors\": [{\"field\",\"message\"}],\"trace_id\"}`.\n- `401`/`403` — `{\"Message\": \"...\"}` (a legacy-vs-Terra key mismatch reads\n  as an AWS-gateway \"explicit deny\" message on the legacy endpoint).\n- `404` — `{\"message\": \"Not Found\"}`.\n- `429` — QPS (10) or daily quota (10,000) exceeded on Discover.\n\nFile v1.1.4:references/web-fallback.md\n\n# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/typeahead`,\n  `/Search?q=`) is a dead end (empty body, 404, needs auth, or a hydrated\n  SPA shell with no SSR data). **Resolve a `locationId` via the Terra\n  `GET /locations/search` endpoint** (`references/terra-endpoints.md` §1),\n  or take it from a TripAdvisor URL, then use this fallback for detail.\n- Individual review **text** is not in the ld+json (no `Review` schema\n  block, no Apollo/redux store) — only the aggregate rating/count. Use the\n  Terra `GET /locations/{id}/reviews` endpoint for review text.\n- If the fetched body isn't valid HTML with an ld+json block (a\n  bot-challenge interstitial slipped through), re-open/refresh the\n  `www.tripadvisor.com` tab and retry.\n\nFile v1.1.4:skill-card.md\n\n## Description:\n\nHelps agents retrieve TripAdvisor location search results, details, photos, and reviews through the Terra API, with a browser-based fallback for public location details.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to look up TripAdvisor places, ratings, photos, and reviews without running an MCP server. A browser fallback can retrieve public details for a known location when an API key is unavailable.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Reading a local .env file may expose a TripAdvisor API key.\n\nMitigation: Provide the key explicitly through an approved secret mechanism rather than reading local credential files.\n\nRisk: Installing a global browser bridge and pairing a signed-in tab can expose browser-session data.\n\nMitigation: Prefer the read-only Terra API; review the bridge before installation and pair only an approved browser tab if the fallback is needed.\n\nRisk: The browser fallback can leave fetched page HTML in a temporary file.\n\nMitigation: Delete temporary HTML after extracting the needed location details.\n\n## Reference(s):\n\n- [TripAdvisor API skill listing](https://clawhub.ai/chrischall/skills/tripadvisor-api)\n- [Terra endpoint recipes](references/terra-endpoints.md)\n- [Browser fallback instructions](references/web-fallback.md)\n- [TripAdvisor developer portal](https://www.tripadvisor.com/developers)\n- [ContextMint Bridge source](https://github.com/nullnet-app/contextmint-bridge)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Shell commands, Guidance]\n\n**Output Format:** [Markdown with shell commands and JSON response examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only location data; the browser fallback provides summary details, not individual review text.]\n\n## Skill Version(s):\n\n1.1.4 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.3: 5 files, 8429 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2087b), SKILL.md (5391b), _meta.json (134b)\n\nFile v1.1.3:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in Transporter\n```\n\nRequires the **Transporter** extension with an open `www.tripadvisor.com`\ntab. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.3:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.3\",\n  \"publishedAt\": 1790351498670\n}\n\nFile v1.1.3:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id calls.\n\n## 4. Location details (`ta_get_location_details` / `src/tools/location.ts`)\n\n`GET /locations/{id}` — path `id` (int), **plural** `/locations/{id}` (the\ndocs' llms.txt index shows the singular form; that 404s). Optional\n`locale` (repeated).\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675\" | jq '{\n  id, geo, name: (.names[] | select(.primary) | .value),\n  rating: .traveler_ratings.overall, address: .addresses[0],\n  phone: .phone_numbers[0].value, url: .urls.tripadvisor.main\n}'\n```\n\nResponse: the full `Location` object directly (not wrapped in `data`) —\n`names`/`descriptions`/`addresses` are language-tagged arrays; the primary\nentry has `\"primary\": true`.\n\n## 5. Location photos (`ta_get_location_photos` / `src/tools/location.ts`)\n\n`GET /locations/{id}/photos` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/photos?size=10\" \\\n  | jq '[.data[] | {id, url: .photo.original_size_url, w: .photo.original_width, h: .photo.original_height}]'\n```\n\nResponse: `{\"data\": [{\"id\",\"location_id\",\"photo\": {\"key\",\"original_size_url\",\"original_height\",\"original_width\",\"media_type\"}, \"publish_ts\", \"source\": {\"name\"}, \"user\"}], \"pagination\": {...}}`.\n\n## 6. Location reviews (`ta_get_location_reviews` / `src/tools/location.ts`)\n\n`GET /locations/{id}/reviews` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/reviews?size=10\" | jq '.data'\n```\n\nResponse: `{\"data\": [...review objects...], \"pagination\": {...}}`.\n\n---\n\n## Error bodies\n\n- `400` — `{\"type\",\"title\",\"status\",\"detail\",\"field_errors\": [{\"field\",\"message\"}],\"trace_id\"}`.\n- `401`/`403` — `{\"Message\": \"...\"}` (a legacy-vs-Terra key mismatch reads\n  as an AWS-gateway \"explicit deny\" message on the legacy endpoint).\n- `404` — `{\"message\": \"Not Found\"}`.\n- `429` — QPS (10) or daily quota (10,000) exceeded on Discover.\n\nFile v1.1.3:references/web-fallback.md\n\n# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/typeahead`,\n  `/Search?q=`) is a dead end (empty body, 404, needs auth, or a hydrated\n  SPA shell with no SSR data). **Resolve a `locationId` via the Terra\n  `GET /locations/search` endpoint** (`references/terra-endpoints.md` §1),\n  or take it from a TripAdvisor URL, then use this fallback for detail.\n- Individual review **text** is not in the ld+json (no `Review` schema\n  block, no Apollo/redux store) — only the aggregate rating/count. Use the\n  Terra `GET /locations/{id}/reviews` endpoint for review text.\n- If the fetched body isn't valid HTML with an ld+json block (a\n  bot-challenge interstitial slipped through), re-open/refresh the\n  `www.tripadvisor.com` tab and retry.\n\nFile v1.1.3:skill-card.md\n\n## Description:\n\nHelps agents retrieve TripAdvisor location searches, nearby places, details, photos, and reviews through read-only API calls, with a browser-based fallback for basic location details.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to look up TripAdvisor places, ratings, photos, and reviews without an MCP server. A browser-session fallback provides basic location details when an API key is unavailable.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Reading or printing a .env file may expose the TripAdvisor API key.\n\nMitigation: Provide the key through a secret manager or environment variable instead of printing it from a .env file.\n\nRisk: The fallback accesses a signed-in browser session and can leave fetched page content in a temporary file.\n\nMitigation: Limit browser access to tripadvisor.com and delete /tmp/ta-location.html if it may contain session-contextualized content.\n\n## Reference(s):\n\n- [TripAdvisor API skill on ClawHub](https://clawhub.ai/chrischall/skills/tripadvisor-api)\n- [TripAdvisor developer portal](https://www.tripadvisor.com/developers)\n- [Terra API endpoint recipes](artifact/references/terra-endpoints.md)\n- [Browser fallback instructions](artifact/references/web-fallback.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Shell commands, JSON, Guidance]\n\n**Output Format:** [Markdown instructions and shell commands with JSON location data]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only location data; browser fallback returns basic details, not individual review text.]\n\n## Skill Version(s):\n\n1.1.3 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.2: 5 files, 8647 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2498b), SKILL.md (5391b), _meta.json (134b)\n\nFile v1.1.2:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in Transporter\n```\n\nRequires the **Transporter** extension with an open `www.tripadvisor.com`\ntab. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.2:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.2\",\n  \"publishedAt\": 1790199919663\n}\n\nFile v1.1.2:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id calls.\n\n## 4. Location details (`ta_get_location_details` / `src/tools/location.ts`)\n\n`GET /locations/{id}` — path `id` (int), **plural** `/locations/{id}` (the\ndocs' llms.txt index shows the singular form; that 404s). Optional\n`locale` (repeated).\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675\" | jq '{\n  id, geo, name: (.names[] | select(.primary) | .value),\n  rating: .traveler_ratings.overall, address: .addresses[0],\n  phone: .phone_numbers[0].value, url: .urls.tripadvisor.main\n}'\n```\n\nResponse: the full `Location` object directly (not wrapped in `data`) —\n`names`/`descriptions`/`addresses` are language-tagged arrays; the primary\nentry has `\"primary\": true`.\n\n## 5. Location photos (`ta_get_location_photos` / `src/tools/location.ts`)\n\n`GET /locations/{id}/photos` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/photos?size=10\" \\\n  | jq '[.data[] | {id, url: .photo.original_size_url, w: .photo.original_width, h: .photo.original_height}]'\n```\n\nResponse: `{\"data\": [{\"id\",\"location_id\",\"photo\": {\"key\",\"original_size_url\",\"original_height\",\"original_width\",\"media_type\"}, \"publish_ts\", \"source\": {\"name\"}, \"user\"}], \"pagination\": {...}}`.\n\n## 6. Location reviews (`ta_get_location_reviews` / `src/tools/location.ts`)\n\n`GET /locations/{id}/reviews` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/reviews?size=10\" | jq '.data'\n```\n\nResponse: `{\"data\": [...review objects...], \"pagination\": {...}}`.\n\n---\n\n## Error bodies\n\n- `400` — `{\"type\",\"title\",\"status\",\"detail\",\"field_errors\": [{\"field\",\"message\"}],\"trace_id\"}`.\n- `401`/`403` — `{\"Message\": \"...\"}` (a legacy-vs-Terra key mismatch reads\n  as an AWS-gateway \"explicit deny\" message on the legacy endpoint).\n- `404` — `{\"message\": \"Not Found\"}`.\n- `429` — QPS (10) or daily quota (10,000) exceeded on Discover.\n\nFile v1.1.2:references/web-fallback.md\n\n# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/typeahead`,\n  `/Search?q=`) is a dead end (empty body, 404, needs auth, or a hydrated\n  SPA shell with no SSR data). **Resolve a `locationId` via the Terra\n  `GET /locations/search` endpoint** (`references/terra-endpoints.md` §1),\n  or take it from a TripAdvisor URL, then use this fallback for detail.\n- Individual review **text** is not in the ld+json (no `Review` schema\n  block, no Apollo/redux store) — only the aggregate rating/count. Use the\n  Terra `GET /locations/{id}/reviews` endpoint for review text.\n- If the fetched body isn't valid HTML with an ld+json block (a\n  bot-challenge interstitial slipped through), re-open/refresh the\n  `www.tripadvisor.com` tab and retry.\n\nFile v1.1.2:skill-card.md\n\n## Description:\n\nQuery TripAdvisor location data for search, nearby places, details, photos, and reviews from a shell with curl against the Terra REST API, with a no-API-key fallback that reads a public location page through the fpx browser bridge.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to retrieve TripAdvisor location data through shell commands for scripts or environments where the MCP server is unavailable. It supports API-key based Terra reads and a smaller browser-bridge fallback for public location details.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: TripAdvisor API keys may be exposed through shell commands, environment handling, or local .env inspection.\n\nMitigation: Set TRIPADVISOR_API_KEY through a normal secret manager or scoped environment and avoid printing or copying secrets into shared logs.\n\nRisk: The fpx fallback uses a signed-in browser bridge and may expose browsing context or temporary fetched HTML.\n\nMitigation: Use a dedicated browser profile restricted to tripadvisor.com, delete temporary fetched HTML, and unpair or remove fpx when the fallback is no longer needed.\n\nRisk: API quotas, upstream errors, bot walls, or page parsing drift may produce missing or incomplete results.\n\nMitigation: Check HTTP status and error bodies, back off on 429 responses, and verify parsed fallback results before relying on them.\n\n## Reference(s):\n\n- [Terra API endpoints](references/terra-endpoints.md)\n- [Web fallback: location detail via fpx](references/web-fallback.md)\n- [TripAdvisor Developers](https://www.tripadvisor.com/developers)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, API Calls, Code, Configuration instructions, Guidance]\n\n**Output Format:** [Markdown with inline bash, JSON, jq, and Python code blocks]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Produces read-only TripAdvisor API and browser-fallback guidance; command results are expected to be JSON or parsed JSON projections.]\n\n## Skill Version(s):\n\n1.1.2 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.1: 5 files, 8721 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2722b), SKILL.md (5391b), _meta.json (134b)\n\nFile v1.1.1:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in Transporter\n```\n\nRequires the **Transporter** extension with an open `www.tripadvisor.com`\ntab. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.1:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.1\",\n  \"publishedAt\": 1790178124039\n}\n\nFile v1.1.1:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id calls.\n\n## 4. Location details (`ta_get_location_details` / `src/tools/location.ts`)\n\n`GET /locations/{id}` — path `id` (int), **plural** `/locations/{id}` (the\ndocs' llms.txt index shows the singular form; that 404s). Optional\n`locale` (repeated).\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675\" | jq '{\n  id, geo, name: (.names[] | select(.primary) | .value),\n  rating: .traveler_ratings.overall, address: .addresses[0],\n  phone: .phone_numbers[0].value, url: .urls.tripadvisor.main\n}'\n```\n\nResponse: the full `Location` object directly (not wrapped in `data`) —\n`names`/`descriptions`/`addresses` are language-tagged arrays; the primary\nentry has `\"primary\": true`.\n\n## 5. Location photos (`ta_get_location_photos` / `src/tools/location.ts`)\n\n`GET /locations/{id}/photos` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/photos?size=10\" \\\n  | jq '[.data[] | {id, url: .photo.original_size_url, w: .photo.original_width, h: .photo.original_height}]'\n```\n\nResponse: `{\"data\": [{\"id\",\"location_id\",\"photo\": {\"key\",\"original_size_url\",\"original_height\",\"original_width\",\"media_type\"}, \"publish_ts\", \"source\": {\"name\"}, \"user\"}], \"pagination\": {...}}`.\n\n## 6. Location reviews (`ta_get_location_reviews` / `src/tools/location.ts`)\n\n`GET /locations/{id}/reviews` — optional `page`, `size` (max 20), `locale`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/104675/reviews?size=10\" | jq '.data'\n```\n\nResponse: `{\"data\": [...review objects...], \"pagination\": {...}}`.\n\n---\n\n## Error bodies\n\n- `400` — `{\"type\",\"title\",\"status\",\"detail\",\"field_errors\": [{\"field\",\"message\"}],\"trace_id\"}`.\n- `401`/`403` — `{\"Message\": \"...\"}` (a legacy-vs-Terra key mismatch reads\n  as an AWS-gateway \"explicit deny\" message on the legacy endpoint).\n- `404` — `{\"message\": \"Not Found\"}`.\n- `429` — QPS (10) or daily quota (10,000) exceeded on Discover.\n\nFile v1.1.1:references/web-fallback.md\n\n# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/typeahead`,\n  `/Search?q=`) is a dead end (empty body, 404, needs auth, or a hydrated\n  SPA shell with no SSR data). **Resolve a `locationId` via the Terra\n  `GET /locations/search` endpoint** (`references/terra-endpoints.md` §1),\n  or take it from a TripAdvisor URL, then use this fallback for detail.\n- Individual review **text** is not in the ld+json (no `Review` schema\n  block, no Apollo/redux store) — only the aggregate rating/count. Use the\n  Terra `GET /locations/{id}/reviews` endpoint for review text.\n- If the fetched body isn't valid HTML with an ld+json block (a\n  bot-challenge interstitial slipped through), re-open/refresh the\n  `www.tripadvisor.com` tab and retry.\n\nFile v1.1.1:skill-card.md\n\n## Description:\n\nQuery TripAdvisor location data for search, nearby results, details, photos, and reviews from a shell with curl against the Terra REST API, with a no-API-key fallback that reads public location details through an fpx browser bridge.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to retrieve TripAdvisor location information from command-line workflows without running the TripAdvisor MCP server. It supports API-key-based Terra calls and a limited browser-backed fallback for public location details.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The workflow uses a TripAdvisor API key and includes an example that reads a local .env file, which could expose credentials in terminal history, logs, or screenshots.\n\nMitigation: Set TRIPADVISOR_API_KEY through a shell environment or secret manager, avoid echoing secrets, and review terminal output before sharing it.\n\nRisk: Fallback mode routes requests through a signed-in browser session, which can expose session context to the fetch workflow.\n\nMitigation: Use a dedicated or logged-out browser profile for fpx where possible and keep the Transporter browser tab limited to the required TripAdvisor page.\n\nRisk: TripAdvisor responses may be incomplete, rate-limited, blocked, or shaped differently across API and browser fallback paths.\n\nMitigation: Check HTTP status codes and parsed fields before relying on results, retry only with backoff, and re-verify browser parsing when public page structure changes.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/chrischall/skills/tripadvisor-api)\n- [TripAdvisor developers](https://www.tripadvisor.com/developers)\n- [Terra API base URL](https://terra.tripadvisor.com/api)\n- [Terra API endpoints](references/terra-endpoints.md)\n- [Web fallback](references/web-fallback.md)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, API Calls, Code, Configuration, Guidance]\n\n**Output Format:** [Markdown with inline shell, Python, jq, and JSON examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only TripAdvisor data retrieval guidance; Terra calls require TRIPADVISOR_API_KEY and fallback mode requires fpx with a browser session.]\n\n## Skill Version(s):\n\n1.1.1 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.0: 5 files, 8573 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2367b), SKILL.md (5391b), _meta.json (134b)\n\nFile v1.1.0:SKILL.md\n\n---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`descriptions`/`addresses` as\n  **arrays** tagged by language — the primary entry has `\"primary\": true`\n  (`jq '.names[] | select(.primary) | .value'`), not a flat `name` field.\n\nFull field lists and all 6 curl+jq recipes: `references/terra-endpoints.md`.\n\n## Output / error contract\n\n- A 2xx body is JSON; pipe to `jq`.\n- `400` — validation error; body is `{type, title, status, detail,\n  field_errors: [{field, message}], trace_id}` — `detail`/`field_errors`\n  name the bad param.\n- `401`/`403` — key missing, invalid, or the wrong API family (legacy key\n  on Terra, or vice versa).\n- `404` — unknown id, or a typo'd path (`/locations/{id}` is **plural**;\n  the singular form 404s).\n- `429` — QPS (10) or daily quota (10,000) exceeded on the Discover tier;\n  back off and retry (the response may carry `Retry-After`).\n\n## Fallback tier: no API key (fpx browser bridge)\n\nTripAdvisor's consumer site (`www.tripadvisor.com`) is DataDome-walled, so\nit can't be curled directly — but a location's public detail page is\nplain server-rendered HTML with a clean `application/ld+json` block\n(name, rating, review count, address, phone, coordinates), reachable with\n**no API key** by routing the fetch through your own signed-in browser\ntab via `fpx` (`@fetchproxy/cli`). Use this when you don't have (or don't\nwant to use) a Terra key, or `ta_get_location_details` is blocked.\n\n```sh\nnpm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in Transporter\n```\n\nRequires the **Transporter** extension with an open `www.tripadvisor.com`\ntab. This covers attractions, hotels, and restaurants — it does **not**\nreturn individual review text (only the aggregate rating/count). Fetch +\nparse recipe: `references/web-fallback.md`.\n\n### fpx exit codes (fetch verbs)\n\n- `0` — success.\n- `2` — bridge unavailable: extension not connected / pairing pending →\n  `fpx pair -p tripadvisor`.\n- `3` — bot wall: the tab hasn't cleared DataDome → open/refresh a\n  `www.tripadvisor.com` tab and retry.\n- `4` — upstream non-2xx from TripAdvisor.\n\n## Notes\n\n- Terra reads only — nothing here mutates TripAdvisor data.\n- This project (`tripadvisor-mcp`) is developed and maintained by AI\n  (Claude Code).\n\nFile v1.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.0\",\n  \"publishedAt\": 1789872628362\n}\n\nFile v1.1.0:references/terra-endpoints.md\n\n# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.prim\n\nArchive v1.0.0: 5 files, 8695 bytes\n\nFiles: references/terra-endpoints.md (4906b), references/web-fallback.md (3693b), skill-card.md (2663b), SKILL.md (5391b), _meta.json (134b)","readmeExcerpt":"Skill: tripadvisor-api Owner: chrischall Summary: Query TripAdvisor location data (search, nearby, details, photos, reviews) straight from a shell with curl against the Terra REST API (terra.tripadvisor.com), instead of running the tripadvisor-mcp server — plus a no-API-key fallback that reads a location's public page through the fpx browser bridge. Use when you want TripAdvisor data without the MCP, in a script, or ","codeSnippets":[],"executableExamples":[{"language":"sh","snippet":"# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'"},{"language":"sh","snippet":"curl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\"},{"language":"sh","snippet":"BASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'"},{"language":"sh","snippet":"curl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'"},{"language":"sh","snippet":"curl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675"},{"language":"sh","snippet":"npm install -g @fetchproxy/cli                      # provides `fpx`\nfpx profile add tripadvisor --domain tripadvisor.com # fetch capability only\nfpx pair -p tripadvisor                              # prints a pair code → approve in ContextMint Bridge"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: tripadvisor-api\ndescription: >-\n  Query TripAdvisor location data (search, nearby, details, photos, reviews)\n  straight from a shell with curl against the Terra REST API\n  (terra.tripadvisor.com), instead of running the tripadvisor-mcp server —\n  plus a no-API-key fallback that reads a location's public page through the\n  fpx browser bridge. Use when you want TripAdvisor data without the MCP, in\n  a script, or on a machine where the MCP isn't installed. Triggers on \"check\n  TripAdvisor\", \"TripAdvisor location/restaurant/hotel/attraction search,\n  details, photos, reviews\", or any TripAdvisor data request that should hit\n  the API directly.\n---\n\n# TripAdvisor Terra API via curl (no MCP)\n\nTripAdvisor's **Terra** API (`terra.tripadvisor.com/api`) is a plain\nAPI-key REST API reachable directly from a server or shell — no browser\nbridge needed. This skill shells out to `curl` with the key in an\n`X-API-Key` header, exactly as `tripadvisor-mcp`'s `src/client.ts` does.\nTerra is the current API (the legacy Content API sunsets 2026-08-31); it\nhas **no write endpoints** — everything here is a read.\n\nA second, smaller tier at the bottom covers the one thing Terra can't do\nwithout a key: reading a location's core details from the public\nconsumer page via the `fpx` browser bridge.\n\n## One-time setup: get a Terra key\n\n```sh\n# Prefer the env var tripadvisor-mcp itself reads (check its .env first):\ngrep -h TRIPADVISOR_API_KEY ~/git/tripadvisor-mcp/.env 2>/dev/null\nexport TRIPADVISOR_API_KEY='...'\n```\n\nIf you don't have one: create a free **Discover**-tier key at\nhttps://www.tripadvisor.com/developers (pay-as-you-go, 10 QPS / 10,000\ncalls/day). A **legacy** Content API key does NOT work here (and vice\nversa) — a mismatched key gets a `403`.\n\n## Core call pattern\n\n```sh\nBASE=https://terra.tripadvisor.com/api\n\ncurl -sS \"$BASE/locations/search?query=Golden%20Gate%20Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json' \\\n  | jq '.data[].location | {id, name: (.names[] | select(.primary) | .value)}'\n```\n\nEvery call needs just the two headers above — no session/cookie, no\nmutual TLS. Ready-to-run recipes for all 6 endpoints are in\n`references/terra-endpoints.md`.\n\n## The one rule: resolve a location id first\n\nDetails/photos/reviews are keyed by numeric `location_id` — get one from\n`ta_search_locations`'s equivalent, `GET /locations/search`, before\ncalling the id-scoped endpoints:\n\n```sh\ncurl -sS \"$BASE/locations/search?query=Golden+Gate+Bridge\" \\\n  -H \"X-API-Key: $TRIPADVISOR_API_KEY\" | jq -r '.data[].location.id'\n# 104675\n```\n\n## Response shapes (quick reference)\n\n- List endpoints (`search`, `nearby`, `reviews`, `photos`) wrap results:\n  `{\"data\": [...], \"pagination\": {\"page\",\"size\",\"total_pages\",\"total_elements\"}}`.\n- `GET /locations` (batch) and `GET /locations/{id}` (details) do **not**\n  wrap in `pagination` — batch returns `{\"data\": [...]}`, details returns\n  the location object directly.\n- A **location** object keys `names`/`des"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"tripadvisor-api\",\n  \"version\": \"1.1.8\",\n  \"publishedAt\": 1791588429793\n}"},{"path":"references/terra-endpoints.md","content":"# Terra API endpoints (curl + jq)\n\nAll paths are relative to `$BASE=https://terra.tripadvisor.com/api`. Every\ncall carries `-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json'`\n(shorthand `\"${H[@]}\"` below). Shapes captured live with a Discover-plan key;\ntranscribed from `tripadvisor-mcp`'s `src/tools/search.ts` + `src/tools/location.ts`\n(each section names its source tool). All 6 are `GET`, all read-only.\n\n```sh\nBASE=https://terra.tripadvisor.com/api\nH=(-H \"X-API-Key: $TRIPADVISOR_API_KEY\" -H 'accept: application/json')\n```\n\nCategories are `RESTAURANT` | `ATTRACTION` | `HOTEL` (uppercase). `size` on\nlist endpoints defaults to 20 and is **capped at 20**.\n\n---\n\n## 1. Location search (`ta_search_locations` / `src/tools/search.ts`)\n\n`GET /locations/search` — `query` (1–500 chars) required; optional\n`category`, `search_type` (default `NAME`), `country_code` (alpha-2),\n`geo_name`, `postal_code` (takes precedence over `geo_name`), `locale`\n(repeated), `page`, `size`.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations/search?query=Golden+Gate+Bridge&category=ATTRACTION\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        geo: .location.geo, rating: .location.traveler_ratings.overall.rating}]'\n```\n\nResponse: `{\"data\": [{\"location\": <Location>, \"matched_value\": {\"language\",\"value\"}}], \"pagination\": {...}}`.\n\n## 2. Nearby search (`ta_search_nearby` / `src/tools/search.ts`)\n\n`GET /locations/nearby` — center is **exactly one** of:\n`lat`+`lon`+`radius` (`unit=MI|KM`, default `MI`), `location_id`+`radius`,\nor the box `sw_lat`,`sw_lon`,`ne_lat`,`ne_lon` (box mode ignores `radius`).\nPlus optional `category`, `min_rating` (1.0–5.0), `include_photo` (bool),\n`sort` (`distance`|`rating`), `page`, `size`, `locale`.\n\n```sh\n# lat/lon + radius\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?lat=37.8199&lon=-122.4783&radius=5&unit=MI&category=RESTAURANT&sort=rating\" \\\n  | jq '[.data[] | {id: .location.id, name: (.location.names[] | select(.primary) | .value),\n        distance_mi: .distance_miles, bearing}]'\n\n# location_id + radius (reference location as center)\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?location_id=104675&radius=2&unit=KM&category=HOTEL\" | jq '.data'\n\n# bounding box\ncurl -sS \"${H[@]}\" \"$BASE/locations/nearby?sw_lat=37.70&sw_lon=-122.55&ne_lat=37.85&ne_lon=-122.35&category=ATTRACTION\" \\\n  | jq '.data'\n```\n\nResponse item: `{\"location\": <Location>, \"bearing\", \"distance_miles\", \"distance_kilometers\"}`.\n\n## 3. Batch multi-get (`ta_get_locations` / `src/tools/location.ts`)\n\n`GET /locations` — repeated `id` param (1–50 ids), required; optional\n`locale`. **No `pagination` wrapper.** Unknown/unlicensed ids are silently\nomitted (not an error) — a malformed id, e.g. one exceeding int32, does 400.\n\n```sh\ncurl -sS \"${H[@]}\" \"$BASE/locations?id=104675&id=93520&id=423942\" \\\n  | jq '[.data[] | {id, name: (.names[] | select(.primary) | .value)}]'\n```\n\nResponse: `{\"data\": [<Location>, ...]}` — cheaper than N single-id c"},{"path":"references/web-fallback.md","content":"# Web fallback: location detail via fpx (no API key)\n\nCovers `ta_web_get_location` (`tripadvisor-mcp`'s `src/tools/web.ts` +\n`src/web/parse.ts`) — the one solid endpoint on the consumer site, reached\nwith **no Terra key** by routing through your own signed-in browser tab.\nShapes captured live 2026-07-04; re-verify if parsing drifts (see\n`docs/TRIPADVISOR-WEB-API.md` in the repo for the full recon).\n\nSetup (once): see `../SKILL.md`'s \"Fallback tier\" section\n(`fpx profile add tripadvisor --domain tripadvisor.com` + `fpx pair -p tripadvisor`).\n\n## Canonical URL — works for every category\n\nTripAdvisor canonicalizes on the `d<id>` segment; the `g<geo>` and the\n`_Review` type prefix are corrected by a same-origin redirect that the\nin-tab fetch follows. **One fixed URL form works whether the id is an\nattraction, hotel, or restaurant** — no need to know the category up front:\n\n```\nhttps://www.tripadvisor.com/Attraction_Review-g1-d<locationId>-Reviews-a-a.html\n```\n\n## Fetch + parse\n\n```sh\nLOCATION_ID=104675\nfpx get \"https://www.tripadvisor.com/Attraction_Review-g1-d${LOCATION_ID}-Reviews-a-a.html\" \\\n  -p tripadvisor > /tmp/ta-location.html\n\n# The page embeds 3 application/ld+json blocks; the business node is the\n# one with BOTH `name` and `aggregateRating` (its @type varies by category:\n# LocalBusiness=attraction, LodgingBusiness=hotel, FoodEstablishment=restaurant).\npython3 - /tmp/ta-location.html <<'PY'\nimport re, json, sys\nhtml = open(sys.argv[1]).read()\nfor m in re.findall(r'<script[^>]*type=[\"\\']application/ld\\+json[\"\\'][^>]*>(.*?)</script>', html, re.S | re.I):\n    try:\n        obj = json.loads(m.strip())\n    except Exception:\n        continue\n    if isinstance(obj, dict) and 'name' in obj and 'aggregateRating' in obj:\n        print(json.dumps(obj))\n        break\nPY\n```\n\nPipe that single-line JSON into `jq` for a slim projection matching what\n`ta_web_get_location` returns:\n\n```sh\n... | jq '{\n  name, type: .[\"@type\"], url,\n  rating: (.aggregateRating.ratingValue | tonumber),\n  review_count: .aggregateRating.reviewCount,\n  best_rating: .aggregateRating.bestRating,\n  telephone, image,\n  latitude: .geo.latitude, longitude: .geo.longitude,\n  same_as: .sameAs, address\n}'\n```\n\nExample fields (attraction, `d104675`):\n\n```jsonc\n{\n  \"@type\": \"LocalBusiness\",\n  \"name\": \"Golden Gate Bridge\",\n  \"url\": \"https://www.tripadvisor.com/Attraction_Review-g60713-d104675-...html\",\n  \"address\": {\"addressLocality\": \"San Francisco\", \"addressRegion\": \"California\", \"addressCountry\": \"US\", \"postalCode\": \"94129\"},\n  \"aggregateRating\": {\"ratingValue\": \"4.7\", \"reviewCount\": 49969, \"bestRating\": 5},\n  \"image\": \"https://dynamic-media-cdn.tripadvisor.com/media/photo-o/.../golden-gate-bridge.jpg?...\",\n  \"telephone\": \"+1 415-921-5858\",\n  \"geo\": {\"latitude\": 37.820026, \"longitude\": -122.47859},\n  \"sameAs\": \"https://www.goldengate.org/\"\n}\n```\n\n## Limits\n\n- No key-free search/typeahead endpoint exists — every plausible one\n  (`/TypeAheadJson`, `/data/1.0/typeahead`, `/api/internal/1.14/t"},{"path":"skill-card.md","content":"## Description:\n\nHelps agents query TripAdvisor locations, photos, and reviews through the read-only Terra API, with a browser-assisted fallback for public location details.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to look up TripAdvisor locations, nearby places, details, photos, and reviews without running an MCP server. Public location details can also be retrieved through a paired browser when an API key is unavailable.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: An API key may be exposed if printed from a local environment file or included in shared command output.\n\nMitigation: Set TRIPADVISOR_API_KEY using a secret manager or shell environment, and avoid printing or sharing the key.\n\nRisk: Pairing the browser fetch bridge grants access to requests through the signed-in TripAdvisor tab.\n\nMitigation: Approve pairing only for the intended TripAdvisor profile and use the bridge only when needed.\n\n## Reference(s):\n\n- [TripAdvisor API skill release](https://clawhub.ai/chrischall/skills/tripadvisor-api)\n- [TripAdvisor developer portal](https://www.tripadvisor.com/developers)\n- [Terra endpoint recipes](artifact/references/terra-endpoints.md)\n- [Browser fallback guide](artifact/references/web-fallback.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Text, JSON, Shell commands, Guidance]\n\n**Output Format:** [Markdown guidance with shell examples and JSON location data]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Read-only location data; review text requires the API rather than the browser fallback.]\n\n## Skill Version(s):\n\n1.1.8 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1682,"uniquenessScore":42,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T08:12:02.871Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T08:12:02.871Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T10:42:57.681Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}