{
  "data": {
    "id": "gsx9VyA0GeR1bwgRX",
    "actId": "sv4kVnROMGAakFpbJ",
    "userId": "IYgBDiXtHOijAaUel",
    "startedAt": "2026-11-04T11:51:57.193Z",
    "finishedAt": "2026-11-04T11:52:00.924Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CLI"
    },
    "stats": {
      "durationMillis": 3614,
      "runTimeSecs": 3.614,
      "computeUnits": 0.004015555555555555,
      "imageSizeBytes": 354482688
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "QYo53EZkJk0prePWY",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"Tripadvisor Place and Review Scraper input\",\n  \"description\": \"Choose a mode, give it a query or Tripadvisor place URLs, and optionally narrow the review export by rating, language, traveler type, month, keyword and sort.\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"mode\": {\n      \"title\": \"Mode\",\n      \"type\": \"string\",\n      \"description\": \"search finds ranked places from a query; details reads one place per URL or ID; reviews exports review rows with optional filters.\",\n      \"editor\": \"select\",\n      \"default\": \"search\",\n      \"prefill\": \"search\",\n      \"enum\": [\n        \"search\",\n        \"details\",\n        \"reviews\"\n      ],\n      \"enumTitles\": [\n        \"Search places\",\n        \"Place details\",\n        \"Reviews\"\n      ]\n    },\n    \"query\": {\n      \"title\": \"Search query\",\n      \"type\": \"string\",\n      \"description\": \"What to search for, for example 'hotels in New York', 'restaurants Paris' or 'Eiffel Tower'. The place family is inferred from words such as hotels, restaurants, museums or things to do.\",\n      \"editor\": \"textfield\",\n      \"prefill\": \"Eiffel Tower\",\n      \"sectionCaption\": \"Search\"\n    },\n    \"location\": {\n      \"title\": \"Location\",\n      \"type\": \"string\",\n      \"description\": \"Optional destination used with query, for example 'New York' or 'Paris'. When set, query can be just 'hotels' or 'restaurants'.\",\n      \"editor\": \"textfield\"\n    },\n    \"startUrls\": {\n      \"title\": \"Place URLs or IDs\",\n      \"type\": \"array\",\n      \"description\": \"Tripadvisor place URLs (Hotel_Review, Restaurant_Review or Attraction_Review) or numeric location IDs. Used by details and reviews modes.\",\n      \"editor\": \"stringList\",\n      \"items\": {\n        \"type\": \"string\"\n      },\n      \"sectionCaption\": \"Targets\"\n    },\n    \"maxItems\": {\n      \"title\": \"Maximum places\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum search results, detail places, or review target places to process. One place can return many reviews.\",\n      \"default\": 20,\n      \"minimum\": 1,\n      \"maximum\": 500,\n      \"prefill\": 1,\n      \"sectionCaption\": \"Limits\"\n    },\n    \"includeDetails\": {\n      \"title\": \"Enrich place details\",\n      \"type\": \"boolean\",\n      \"description\": \"Fetches amenities and a larger photo for place rows. HTML enrichment is used in details mode when the JSON fields are missing.\",\n      \"default\": true,\n      \"prefill\": false,\n      \"sectionCaption\": \"Details\"\n    },\n    \"maxReviews\": {\n      \"title\": \"Maximum reviews per place\",\n      \"type\": \"integer\",\n      \"description\": \"Reviews to collect for each target place in reviews mode. Upstream returns 20 per request; the actor paginates until this cap.\",\n      \"default\": 20,\n      \"minimum\": 1,\n      \"maximum\": 500,\n      \"prefill\": 20,\n      \"sectionCaption\": \"Reviews\"\n    },\n    \"reviewSort\": {\n      \"title\": \"Review sort\",\n      \"type\": \"string\",\n      \"description\": \"Order of the review stream. Attractions automatically use DETAILED for MOST_RECENT so product reviews do not mix into the attraction's own reviews.\",\n      \"editor\": \"select\",\n      \"default\": \"MOST_RECENT\",\n      \"enum\": [\n        \"MOST_RECENT\",\n        \"MOST_HELPFUL\",\n        \"DETAILED\"\n      ],\n      \"enumTitles\": [\n        \"Most recent\",\n        \"Most helpful\",\n        \"Detailed\"\n      ],\n      \"sectionCaption\": \"Review filters\",\n      \"sectionDescription\": \"Optional filters for the review export. They apply only in reviews mode.\"\n    },\n    \"reviewRating\": {\n      \"title\": \"Review rating\",\n      \"type\": \"string\",\n      \"description\": \"Only return reviews with this bubble rating.\",\n      \"editor\": \"select\",\n      \"default\": \"ANY\",\n      \"enum\": [\n        \"ANY\",\n        \"1\",\n        \"2\",\n        \"3\",\n        \"4\",\n        \"5\"\n      ],\n      \"enumTitles\": [\n        \"Any rating\",\n        \"1 star\",\n        \"2 stars\",\n        \"3 stars\",\n        \"4 stars\",\n        \"5 stars\"\n      ]\n    },\n    \"reviewLanguage\": {\n      \"title\": \"Review language\",\n      \"type\": \"string\",\n      \"description\": \"Only return reviews written in this language.\",\n      \"editor\": \"select\",\n      \"default\": \"ANY\",\n      \"enum\": [\n        \"ANY\",\n        \"en\",\n        \"es\",\n        \"de\",\n        \"fr\",\n        \"it\",\n        \"pt\",\n        \"nl\",\n        \"ru\",\n        \"ja\",\n        \"zhCN\",\n        \"zhTW\",\n        \"ko\",\n        \"ar\",\n        \"tr\",\n        \"pl\",\n        \"sv\",\n        \"da\",\n        \"no\",\n        \"fi\",\n        \"cs\",\n        \"el\",\n        \"hu\",\n        \"iw\",\n        \"in\",\n        \"th\",\n        \"vi\",\n        \"ro\",\n        \"uk\",\n        \"bg\",\n        \"hr\",\n        \"sk\",\n        \"sr\",\n        \"sl\",\n        \"lt\",\n        \"lv\",\n        \"et\",\n        \"ca\",\n        \"ms\",\n        \"tl\",\n        \"hi\"\n      ],\n      \"enumTitles\": [\n        \"Any language\",\n        \"English\",\n        \"Spanish\",\n        \"German\",\n        \"French\",\n        \"Italian\",\n        \"Portuguese\",\n        \"Dutch\",\n        \"Russian\",\n        \"Japanese\",\n        \"Chinese (Simplified)\",\n        \"Chinese (Traditional)\",\n        \"Korean\",\n        \"Arabic\",\n        \"Turkish\",\n        \"Polish\",\n        \"Swedish\",\n        \"Danish\",\n        \"Norwegian\",\n        \"Finnish\",\n        \"Czech\",\n        \"Greek\",\n        \"Hungarian\",\n        \"Hebrew\",\n        \"Indonesian\",\n        \"Thai\",\n        \"Vietnamese\",\n        \"Romanian\",\n        \"Ukrainian\",\n        \"Bulgarian\",\n        \"Croatian\",\n        \"Slovak\",\n        \"Serbian\",\n        \"Slovenian\",\n        \"Lithuanian\",\n        \"Latvian\",\n        \"Estonian\",\n        \"Catalan\",\n        \"Malay\",\n        \"Filipino\",\n        \"Hindi\"\n      ]\n    },\n    \"reviewTripType\": {\n      \"title\": \"Traveler type\",\n      \"type\": \"string\",\n      \"description\": \"Only return reviews from this traveler type.\",\n      \"editor\": \"select\",\n      \"default\": \"ANY\",\n      \"enum\": [\n        \"ANY\",\n        \"FAMILY\",\n        \"COUPLES\",\n        \"SOLO\",\n        \"BUSINESS\",\n        \"FRIENDS\"\n      ],\n      \"enumTitles\": [\n        \"Any traveler type\",\n        \"Family\",\n        \"Couples\",\n        \"Solo\",\n        \"Business\",\n        \"Friends\"\n      ]\n    },\n    \"reviewMonth\": {\n      \"title\": \"Month of visit\",\n      \"type\": \"string\",\n      \"description\": \"Only return reviews submitted in this month.\",\n      \"editor\": \"select\",\n      \"default\": \"ANY\",\n      \"enum\": [\n        \"ANY\",\n        \"JANUARY\",\n        \"FEBRUARY\",\n        \"MARCH\",\n        \"APRIL\",\n        \"MAY\",\n        \"JUNE\",\n        \"JULY\",\n        \"AUGUST\",\n        \"SEPTEMBER\",\n        \"OCTOBER\",\n        \"NOVEMBER\",\n        \"DECEMBER\"\n      ],\n      \"enumTitles\": [\n        \"Any month\",\n        \"January\",\n        \"February\",\n        \"March\",\n        \"April\",\n        \"May\",\n        \"June\",\n        \"July\",\n        \"August\",\n        \"September\",\n        \"October\",\n        \"November\",\n        \"December\"\n      ]\n    },\n    \"reviewKeyword\": {\n      \"title\": \"Review keyword\",\n      \"type\": \"string\",\n      \"description\": \"Only return reviews whose text matches this keyword, for example 'pool' or 'breakfast'.\",\n      \"editor\": \"textfield\"\n    },\n    \"proxyConfiguration\": {\n      \"title\": \"Proxy configuration\",\n      \"type\": \"object\",\n      \"description\": \"Optional. The actor tries direct access first, then the free Apify datacenter proxy, and only escalates after a real block. You do not need to configure a proxy to run it.\",\n      \"editor\": \"proxy\",\n      \"sectionCaption\": \"Proxy\",\n      \"sectionDescription\": \"Leave empty unless you want to supply your own proxy. Direct access is attempted first.\"\n    }\n  },\n  \"required\": []\n}",
    "readme": "# TripAdvisor Hotel, Restaurant & Attraction Finder\r\n\r\nRead Tripadvisor places and reviews in one actor. Search a destination for ranked hotels, restaurants and attractions, open a specific place by its Tripadvisor URL or numeric ID, or export a review stream with server-side filters. Everything works without a Tripadvisor account, API key or cookie.\r\n\r\n## Modes\r\n\r\n| Mode | What it does | Main inputs |\r\n|---|---|---|\r\n| `search` | Finds ranked places through Tripadvisor listing pages. If those pages are unavailable, it falls back to the GraphQL type-ahead index. | `query`, optional `location` |\r\n| `details` | Reads one place per URL or ID from the place page JSON-LD and embedded data, including amenities and a larger photo when published. | `startUrls` |\r\n| `reviews` | Reads reviews for each target place, 20 per request, with offset pagination and filters. Targets can come from URLs, IDs, or a search query. | `startUrls` or `query`, review filters |\r\n\r\nEvery record is a flat JSON object. Place rows carry `recordType: \"place\"`, review rows carry `recordType: \"review\"`, and both include `sourceUrl` and `scrapedAt`. Empty fields are omitted at every depth, so there are no nulls, empty strings, empty arrays or empty objects in the dataset.\r\n\r\n## Place fields\r\n\r\nCurrent fields: `id`, `name`, `type`, `url`, `ratingValue`, `reviewCount`, `ranking`, `priceRange`, `cuisine`, `phone`, `email`, `address`, `lat`, `lng`, `amenities`, `photos`, `sourceUrl`, `scrapedAt`, `recordType`, `detailSource`, `detailStatus`.\r\n\r\nBackward-compatible legacy fields are always restored on place rows: `locationId`, `subcategory`, `street`, `city`, `state`, `country`, `postalCode`, `latitude`, `longitude`, `rating`, `numberOfReviews`, `rankingPosition`, `rankingString`, `priceLevel`, `website`, `hotelClass`, `hours`, `description`, `neighborhoods`, `webUrl`, `isClosed`, `photoUrl`, `searchQuery`, `scrapeTimestamp`.\r\n\r\n`type` is `hotel`, `restaurant` or `attraction`. `ratingValue`, `reviewCount`, `lat` and `lng` are numeric. The legacy `rating`, `numberOfReviews`, `latitude` and `longitude` fields are strings, matching the pre-revamp contract. `amenities` and `photos` are arrays of strings. `ranking` is the full Tripadvisor ranking text when the place page publishes it.\r\n\r\nA TypeAhead fallback row carries `detailSource: \"typeaheadFallback\"` and `detailStatus: \"partial\"`; a normal detail-page row carries `detailStatus: \"complete\"`. Media URLs are checked for scheme, host and extension before they are published.\r\n\r\n## Review fields\r\n\r\n`id`, `placeId`, `title`, `text`, `rating`, `date`, `tripType`, `language`, `author`, `authorLocation`, `helpfulVotes`, `sourceUrl`, `scrapedAt`, `recordType`.\r\n\r\n`date` is the review submission timestamp, `tripType` is the traveler type reported by the reviewer, and `authorLocation` is the reviewer's published hometown.\r\n\r\n## Input\r\n\r\n| Field | Type | Default | Description |\r\n|---|---|---|---|\r\n| `mode` | select | `search` | `search`, `details` or `reviews`. |\r\n| `query` | string | - | Search phrase, for example `hotels in New York` or `Eiffel Tower`. Also used by `reviews` when no URLs are given. |\r\n| `location` | string | - | Optional destination for search, for example `New York`. With this set, `query` can be just `hotels`. |\r\n| `startUrls` | string list | - | Tripadvisor place URLs or numeric location IDs. Used by `details` and `reviews`. |\r\n| `maxItems` | integer 1-500 | `20` | Maximum places to return in `search`, process in `details`, or use as review targets in `reviews`. |\r\n| `includeDetails` | boolean | `true` | Fetch extra place data: key amenities, a larger photo, and HTML enrichment when the JSON fields are missing. |\r\n| `maxReviews` | integer 1-500 | `20` | Reviews per place in `reviews` mode. |\r\n| `reviewSort` | select | `MOST_RECENT` | `MOST_RECENT`, `MOST_HELPFUL` or `DETAILED`. Attractions automatically use `DETAILED` for `MOST_RECENT` so bookable product reviews do not mix into the attraction's reviews. |\r\n| `reviewRating` | select | `ANY` | `ANY` or 1-5. |\r\n| `reviewLanguage` | select | `ANY` | Common Tripadvisor language tags such as `en`, `de`, `fr` or `es`. |\r\n| `reviewTripType` | select | `ANY` | `FAMILY`, `COUPLES`, `SOLO`, `BUSINESS` or `FRIENDS`. |\r\n| `reviewMonth` | select | `ANY` | `JANUARY` through `DECEMBER`. |\r\n| `reviewKeyword` | string | - | Text that must appear in the review. |\r\n| `proxyConfiguration` | object | - | Optional. Direct access is tried first. |\r\n\r\nAt least one search phrase or start URL is required, depending on the mode. Search and details modes need their own target. Reviews mode accepts either start URLs or a query.\r\n\r\n## Examples\r\n\r\nOpen one hotel and include amenities:\r\n\r\n```json\r\n{\r\n  \"mode\": \"details\",\r\n  \"startUrls\": [\r\n    \"https://www.tripadvisor.com/Hotel_Review-g60763-d675616-Reviews-The_Plaza_New_York_A_Fairmont_Managed_Hotel-New_York_City_New_York.html\"\r\n  ],\r\n  \"maxItems\": 1,\r\n  \"includeDetails\": true\r\n}\r\n```\r\n\r\nSearch hotels in New York:\r\n\r\n```json\r\n{\r\n  \"mode\": \"search\",\r\n  \"query\": \"hotels\",\r\n  \"location\": \"New York\",\r\n  \"maxItems\": 10,\r\n  \"includeDetails\": false\r\n}\r\n```\r\n\r\nExport recent five-star English reviews for a place:\r\n\r\n```json\r\n{\r\n  \"mode\": \"reviews\",\r\n  \"startUrls\": [\"675616\"],\r\n  \"maxItems\": 1,\r\n  \"maxReviews\": 100,\r\n  \"reviewSort\": \"MOST_RECENT\",\r\n  \"reviewRating\": \"5\",\r\n  \"reviewLanguage\": \"en\"\r\n}\r\n```\r\n\r\nSearch a city and then export its reviews:\r\n\r\n```json\r\n{\r\n  \"mode\": \"reviews\",\r\n  \"query\": \"restaurants in Paris\",\r\n  \"maxItems\": 5,\r\n  \"maxReviews\": 20\r\n}\r\n```\r\n\r\n## How search works\r\n\r\nThe actor resolves the destination with the type-ahead GraphQL index and always sends the full free-text query first, even when the query contains a family word such as `restaurants`. Queries like `sushi restaurants in New York` therefore keep `sushi` in the request instead of browsing every restaurant in the city.\r\n\r\nRanked listing pages (`Hotels`, `Restaurants` and `Attractions`) 30 places at a time are used as a supplement. When listing rows are added for a free-text query, they are filtered client-side by the remaining terms against name, cuisine and description; unrelated rows are dropped and reported as `relevance_filtered` in the run status. TypeAhead results are limited to 20 per request, so a free-text-only query can stop at 20 rows; listing supplement and pagination extend family searches up to `maxItems`.\r\n\r\nDuplicates are removed by place ID, and TypeAhead results keep their order ahead of listing supplements. `search` never uses a browser, a cookie or a login. Listing pages use a Safari TLS profile; the JSON APIs are called with plain HTTP. With `includeDetails: true`, each place is opened once to fill the full ranking, amenities and photo.\r\n\r\n## How details works\r\n\r\nPlace IDs are read from URLs such as `/Hotel_Review-g60763-d675616-...` or from numeric IDs. Each place page is read as HTML and its schema.org JSON-LD plus server-rendered data supply the place fields, including rating, review count, ranking, price range, contacts, coordinates, amenities, cuisine and photos.\r\n\r\nWhen only a numeric ID is given, the actor opens a category-agnostic Tripadvisor URL and follows the canonical redirect to the hotel, restaurant or attraction page. Redirected URLs are accepted when they keep the same location ID; a redirect to a different ID or to a category page is treated as not found, so data is never attributed to the wrong place.\r\n\r\nIf a detail page is blocked, details mode falls back to the public TypeAhead record for the same location ID, including ID-only targets with no URL. The fallback is attempted even when the only target is a numeric ID. If TypeAhead cannot identify the place, the review clients resolve the type as a last resort (`detailSource: \"reviewTypeFallback\"`). Those rows are marked `detailStatus: \"partial\"` and counted as `details_fallback` in the run status. For reviews, an ID-only target whose detail page cannot resolve the place type also tries the three review clients before the run is marked blocked.\r\n\r\nUnsupported Tripadvisor entities such as activities, cruises and airlines are skipped with a counter instead of failing the whole run.\r\n\r\n## How reviews works\r\n\r\nReviews come from the public reviews GraphQL endpoint. Each request returns at most 20 reviews; the actor pages by offset until `maxReviews`, the place total, or the run cap is reached. Filters are sent to the server, not applied after downloading everything.\r\n\r\nUnlike many review tools, the actor filters every row by the target location ID. Attractions are read with the `DETAILED` sort when `MOST_RECENT` is requested, which keeps bookable product reviews out of the attraction's own review stream.\r\n\r\n## Limits\r\n\r\n- 20 results per TypeAhead request. Free-text-only queries can therefore stop at 20 unless listing pages add relevant rows.\r\n- Search listing pages hold 30 places; up to 17 pages (500 places) are read per family, matching the `maxItems` ceiling.\r\n- 500 reviews per place per run (a product cap; the upstream offset pagination was verified past 5,000).\r\n- 10,000 reviews per run across all targets.\r\n- 500 places per run.\r\n- Reviews are deduplicated by review ID and places by location ID.\r\n- Media URLs are validated for scheme, host and extension, but are not rehosted; a hotlink-blocked CDN URL can still fail in a consumer application.\r\n\r\nThe actor fails the run when it produces zero records or when every request is blocked. If only some targets or pages fail, it pushes the records it has and reports the partial counts in the run status, including `details_fallback` and `relevance_filtered`.\r\n\r\n## Proxy and anti-bot behaviour\r\n\r\nAccess is direct first. If Tripadvisor returns a real block, the actor tries the free Apify datacenter proxy (`AUTO`). It only moves to the `RESIDENTIAL` group after `AUTO` is also blocked. A user-supplied `proxyConfiguration` is used after a direct block. You do not need to configure anything for a normal run.\r\n\r\nEscalation is per request: every JSON or HTML request starts at `direct` and only that request moves up the ladder after a block. A blocked detail page therefore does not force later TypeAhead or review requests onto a paid rung.\r\n\r\nThe TypeAhead and reviews GraphQL endpoints are the primary path for discovery and reviews. Place details are read from the place page HTML, which is fetched with the Safari TLS profile and only when a place record is needed.\r\n\r\n## FAQ\r\n\r\n**Do I need a Tripadvisor account or API key?**\r\nNo. The actor reads public place and review data. It does not log in, and it does not need user cookies.\r\n\r\n**Do I need a proxy?**\r\nNo. Direct access is tried first and works for the JSON APIs. The actor escalates automatically only after a block.\r\n\r\n**Why is `amenities` missing for some places?**\r\nTripadvisor publishes amenities mainly for hotels. Restaurants and attractions often have none, and the field is omitted rather than filled with a placeholder.\r\n\r\n**Why are there fewer reviews than the total on the page?**\r\nThe review count on a place page can include reviews in many languages and, for attractions, reviews from bookable products. The actor returns the reviews that match the target place and your filters, up to `maxReviews`.\r\n\r\n**Why does a search return fewer places than `maxItems`?**\r\nTripadvisor may not render enough ranked cards for a destination, a page may be unavailable, or a free-text TypeAhead query may return at most 20 rows. The actor supplements TypeAhead with filtered listing pages and reports `relevance_filtered`, `listing_failures` and other partial counts in the status message.\r\n\r\n**Are the records always the same shape?**\r\nNo. Empty fields are removed, so a restaurant row has `cuisine` while a hotel row may have `amenities`. Every record keeps the identity, source and timestamp fields.\r\n\r\n**Is this affiliated with Tripadvisor?**\r\nNo. This is an independent, third-party actor that reads publicly available Tripadvisor data. It is not affiliated with or endorsed by Tripadvisor.\r\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "tripadvisor-hotel-restaurant-and-attraction-finder",
      "title": "TripAdvisor Hotel, Restaurant & Attraction Finder",
      "description": "Search Tripadvisor by phrase, read place details from URLs or IDs, and export reviews with rating, language, traveler type, month, keyword and sort filters.",
      "version": "2.0",
      "buildTag": "latest",
      "meta": {
        "templateId": "python-start"
      },
      "input": {
        "title": "Tripadvisor Place and Review Scraper input",
        "description": "Choose a mode, give it a query or Tripadvisor place URLs, and optionally narrow the review export by rating, language, traveler type, month, keyword and sort.",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "mode": {
            "title": "Mode",
            "type": "string",
            "description": "search finds ranked places from a query; details reads one place per URL or ID; reviews exports review rows with optional filters.",
            "editor": "select",
            "default": "search",
            "prefill": "search",
            "enum": [
              "search",
              "details",
              "reviews"
            ],
            "enumTitles": [
              "Search places",
              "Place details",
              "Reviews"
            ]
          },
          "query": {
            "title": "Search query",
            "type": "string",
            "description": "What to search for, for example 'hotels in New York', 'restaurants Paris' or 'Eiffel Tower'. The place family is inferred from words such as hotels, restaurants, museums or things to do.",
            "editor": "textfield",
            "prefill": "Eiffel Tower",
            "sectionCaption": "Search"
          },
          "location": {
            "title": "Location",
            "type": "string",
            "description": "Optional destination used with query, for example 'New York' or 'Paris'. When set, query can be just 'hotels' or 'restaurants'.",
            "editor": "textfield"
          },
          "startUrls": {
            "title": "Place URLs or IDs",
            "type": "array",
            "description": "Tripadvisor place URLs (Hotel_Review, Restaurant_Review or Attraction_Review) or numeric location IDs. Used by details and reviews modes.",
            "editor": "stringList",
            "items": {
              "type": "string"
            },
            "sectionCaption": "Targets"
          },
          "maxItems": {
            "title": "Maximum places",
            "type": "integer",
            "description": "Maximum search results, detail places, or review target places to process. One place can return many reviews.",
            "default": 20,
            "minimum": 1,
            "maximum": 500,
            "prefill": 1,
            "sectionCaption": "Limits"
          },
          "includeDetails": {
            "title": "Enrich place details",
            "type": "boolean",
            "description": "Fetches amenities and a larger photo for place rows. HTML enrichment is used in details mode when the JSON fields are missing.",
            "default": true,
            "prefill": false,
            "sectionCaption": "Details"
          },
          "maxReviews": {
            "title": "Maximum reviews per place",
            "type": "integer",
            "description": "Reviews to collect for each target place in reviews mode. Upstream returns 20 per request; the actor paginates until this cap.",
            "default": 20,
            "minimum": 1,
            "maximum": 500,
            "prefill": 20,
            "sectionCaption": "Reviews"
          },
          "reviewSort": {
            "title": "Review sort",
            "type": "string",
            "description": "Order of the review stream. Attractions automatically use DETAILED for MOST_RECENT so product reviews do not mix into the attraction's own reviews.",
            "editor": "select",
            "default": "MOST_RECENT",
            "enum": [
              "MOST_RECENT",
              "MOST_HELPFUL",
              "DETAILED"
            ],
            "enumTitles": [
              "Most recent",
              "Most helpful",
              "Detailed"
            ],
            "sectionCaption": "Review filters",
            "sectionDescription": "Optional filters for the review export. They apply only in reviews mode."
          },
          "reviewRating": {
            "title": "Review rating",
            "type": "string",
            "description": "Only return reviews with this bubble rating.",
            "editor": "select",
            "default": "ANY",
            "enum": [
              "ANY",
              "1",
              "2",
              "3",
              "4",
              "5"
            ],
            "enumTitles": [
              "Any rating",
              "1 star",
              "2 stars",
              "3 stars",
              "4 stars",
              "5 stars"
            ]
          },
          "reviewLanguage": {
            "title": "Review language",
            "type": "string",
            "description": "Only return reviews written in this language.",
            "editor": "select",
            "default": "ANY",
            "enum": [
              "ANY",
              "en",
              "es",
              "de",
              "fr",
              "it",
              "pt",
              "nl",
              "ru",
              "ja",
              "zhCN",
              "zhTW",
              "ko",
              "ar",
              "tr",
              "pl",
              "sv",
              "da",
              "no",
              "fi",
              "cs",
              "el",
              "hu",
              "iw",
              "in",
              "th",
              "vi",
              "ro",
              "uk",
              "bg",
              "hr",
              "sk",
              "sr",
              "sl",
              "lt",
              "lv",
              "et",
              "ca",
              "ms",
              "tl",
              "hi"
            ],
            "enumTitles": [
              "Any language",
              "English",
              "Spanish",
              "German",
              "French",
              "Italian",
              "Portuguese",
              "Dutch",
              "Russian",
              "Japanese",
              "Chinese (Simplified)",
              "Chinese (Traditional)",
              "Korean",
              "Arabic",
              "Turkish",
              "Polish",
              "Swedish",
              "Danish",
              "Norwegian",
              "Finnish",
              "Czech",
              "Greek",
              "Hungarian",
              "Hebrew",
              "Indonesian",
              "Thai",
              "Vietnamese",
              "Romanian",
              "Ukrainian",
              "Bulgarian",
              "Croatian",
              "Slovak",
              "Serbian",
              "Slovenian",
              "Lithuanian",
              "Latvian",
              "Estonian",
              "Catalan",
              "Malay",
              "Filipino",
              "Hindi"
            ]
          },
          "reviewTripType": {
            "title": "Traveler type",
            "type": "string",
            "description": "Only return reviews from this traveler type.",
            "editor": "select",
            "default": "ANY",
            "enum": [
              "ANY",
              "FAMILY",
              "COUPLES",
              "SOLO",
              "BUSINESS",
              "FRIENDS"
            ],
            "enumTitles": [
              "Any traveler type",
              "Family",
              "Couples",
              "Solo",
              "Business",
              "Friends"
            ]
          },
          "reviewMonth": {
            "title": "Month of visit",
            "type": "string",
            "description": "Only return reviews submitted in this month.",
            "editor": "select",
            "default": "ANY",
            "enum": [
              "ANY",
              "JANUARY",
              "FEBRUARY",
              "MARCH",
              "APRIL",
              "MAY",
              "JUNE",
              "JULY",
              "AUGUST",
              "SEPTEMBER",
              "OCTOBER",
              "NOVEMBER",
              "DECEMBER"
            ],
            "enumTitles": [
              "Any month",
              "January",
              "February",
              "March",
              "April",
              "May",
              "June",
              "July",
              "August",
              "September",
              "October",
              "November",
              "December"
            ]
          },
          "reviewKeyword": {
            "title": "Review keyword",
            "type": "string",
            "description": "Only return reviews whose text matches this keyword, for example 'pool' or 'breakfast'.",
            "editor": "textfield"
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Optional. The actor tries direct access first, then the free Apify datacenter proxy, and only escalates after a real block. You do not need to configure a proxy to run it.",
            "editor": "proxy",
            "sectionCaption": "Proxy",
            "sectionDescription": "Leave empty unless you want to supply your own proxy. Direct access is attempted first."
          }
        },
        "required": []
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Tripadvisor Place and Review Scraper output",
        "type": "object",
        "description": "One row per place in search/details modes and one row per review in reviews mode. Empty fields are omitted at every depth. Every record carries recordType, sourceUrl and scrapedAt. Legacy place names are kept for backward compatibility; rating, numberOfReviews, latitude and longitude are strings, while ratingValue, reviewCount, lat and lng are numeric.",
        "properties": {
          "recordType": {
            "title": "Record type",
            "type": "string",
            "description": "place or review",
            "template": "{{recordType}}"
          },
          "sourceUrl": {
            "title": "Source URL",
            "type": "string",
            "description": "Tripadvisor page the record came from",
            "template": "{{sourceUrl}}"
          },
          "scrapedAt": {
            "title": "Scraped at",
            "type": "string",
            "description": "ISO timestamp of the run",
            "template": "{{scrapedAt}}"
          },
          "id": {
            "title": "ID",
            "type": "string",
            "description": "Place ID for place rows, review ID for review rows",
            "template": "{{id}}"
          },
          "locationId": {
            "title": "Legacy location ID",
            "type": "string",
            "description": "Legacy alias of id for place rows",
            "template": "{{locationId}}"
          },
          "name": {
            "title": "Place name",
            "type": "string",
            "description": "Place name",
            "template": "{{name}}"
          },
          "type": {
            "title": "Place type",
            "type": "string",
            "description": "hotel, restaurant or attraction",
            "template": "{{type}}"
          },
          "subcategory": {
            "title": "Subcategory",
            "type": "string",
            "description": "Legacy specific subcategory label; falls back to the place type",
            "template": "{{subcategory}}"
          },
          "url": {
            "title": "Place URL",
            "type": "string",
            "description": "Canonical Tripadvisor place page",
            "template": "{{url}}"
          },
          "webUrl": {
            "title": "Legacy web URL",
            "type": "string",
            "description": "Legacy alias of url",
            "template": "{{webUrl}}"
          },
          "rating": {
            "title": "Rating",
            "type": "string",
            "description": "Legacy bubble rating as text, 0-5",
            "template": "{{rating}}"
          },
          "ratingValue": {
            "title": "Numeric rating",
            "type": "string",
            "description": "Numeric bubble rating, 0-5",
            "template": "{{ratingValue}}"
          },
          "reviewCount": {
            "title": "Review count",
            "type": "string",
            "description": "Numeric total number of reviews for the place",
            "template": "{{reviewCount}}"
          },
          "numberOfReviews": {
            "title": "Legacy number of reviews",
            "type": "string",
            "description": "Legacy review count as text",
            "template": "{{numberOfReviews}}"
          },
          "ranking": {
            "title": "Ranking",
            "type": "string",
            "description": "Tripadvisor ranking text, for example #13 of 588 hotels in New York City",
            "template": "{{ranking}}"
          },
          "rankingString": {
            "title": "Legacy ranking string",
            "type": "string",
            "description": "Legacy alias of ranking",
            "template": "{{rankingString}}"
          },
          "rankingPosition": {
            "title": "Ranking position",
            "type": "string",
            "description": "Numeric rank parsed from the ranking string",
            "template": "{{rankingPosition}}"
          },
          "priceRange": {
            "title": "Price range",
            "type": "string",
            "description": "Price range text published by Tripadvisor",
            "template": "{{priceRange}}"
          },
          "priceLevel": {
            "title": "Price level",
            "type": "string",
            "description": "Price level symbols when published",
            "template": "{{priceLevel}}"
          },
          "cuisine": {
            "title": "Cuisine",
            "type": "string",
            "description": "Restaurant cuisines",
            "template": "{{cuisine}}"
          },
          "phone": {
            "title": "Phone",
            "type": "string",
            "description": "Phone number",
            "template": "{{phone}}"
          },
          "email": {
            "title": "Email",
            "type": "string",
            "description": "Published email",
            "template": "{{email}}"
          },
          "website": {
            "title": "Website",
            "type": "string",
            "description": "Official website URL when published",
            "template": "{{website}}"
          },
          "hotelClass": {
            "title": "Hotel class",
            "type": "string",
            "description": "Hotel star rating when published",
            "template": "{{hotelClass}}"
          },
          "hours": {
            "title": "Hours",
            "type": "string",
            "description": "Opening hours text when published",
            "template": "{{hours}}"
          },
          "description": {
            "title": "Description",
            "type": "string",
            "description": "Place description when published",
            "template": "{{description}}"
          },
          "neighborhoods": {
            "title": "Neighborhoods",
            "type": "string",
            "description": "Neighborhood names when published",
            "template": "{{neighborhoods}}"
          },
          "address": {
            "title": "Address",
            "type": "string",
            "description": "Full address",
            "template": "{{address}}"
          },
          "street": {
            "title": "Street",
            "type": "string",
            "description": "Street address",
            "template": "{{street}}"
          },
          "city": {
            "title": "City",
            "type": "string",
            "description": "City name",
            "template": "{{city}}"
          },
          "state": {
            "title": "State or province",
            "type": "string",
            "description": "State or province",
            "template": "{{state}}"
          },
          "country": {
            "title": "Country",
            "type": "string",
            "description": "Country name",
            "template": "{{country}}"
          },
          "postalCode": {
            "title": "Postal code",
            "type": "string",
            "description": "Postal or ZIP code",
            "template": "{{postalCode}}"
          },
          "lat": {
            "title": "Numeric latitude",
            "type": "string",
            "description": "Numeric latitude",
            "template": "{{lat}}"
          },
          "lng": {
            "title": "Numeric longitude",
            "type": "string",
            "description": "Numeric longitude",
            "template": "{{lng}}"
          },
          "latitude": {
            "title": "Legacy latitude",
            "type": "string",
            "description": "Legacy latitude as text",
            "template": "{{latitude}}"
          },
          "longitude": {
            "title": "Legacy longitude",
            "type": "string",
            "description": "Legacy longitude as text",
            "template": "{{longitude}}"
          },
          "amenities": {
            "title": "Amenities",
            "type": "string",
            "description": "Hotel amenities",
            "template": "{{amenities}}"
          },
          "photos": {
            "title": "Photos",
            "type": "string",
            "description": "Place photo URLs",
            "template": "{{photos}}"
          },
          "photoUrl": {
            "title": "Legacy photo URL",
            "type": "string",
            "description": "Legacy alias of the first photo",
            "template": "{{photoUrl}}"
          },
          "searchQuery": {
            "title": "Search query",
            "type": "string",
            "description": "The search query that found the place",
            "template": "{{searchQuery}}"
          },
          "isClosed": {
            "title": "Is closed",
            "type": "string",
            "description": "Whether the place is permanently closed, as text",
            "template": "{{isClosed}}"
          },
          "scrapeTimestamp": {
            "title": "Legacy scrape timestamp",
            "type": "string",
            "description": "Legacy alias of scrapedAt",
            "template": "{{scrapeTimestamp}}"
          },
          "detailSource": {
            "title": "Detail source",
            "type": "string",
            "description": "detailPage or typeaheadFallback",
            "template": "{{detailSource}}"
          },
          "detailStatus": {
            "title": "Detail status",
            "type": "string",
            "description": "complete or partial when only a TypeAhead fallback was available",
            "template": "{{detailStatus}}"
          },
          "placeId": {
            "title": "Place ID",
            "type": "string",
            "description": "Place ID for review rows",
            "template": "{{placeId}}"
          },
          "title": {
            "title": "Review title",
            "type": "string",
            "description": "Review title",
            "template": "{{title}}"
          },
          "text": {
            "title": "Review text",
            "type": "string",
            "description": "Review body",
            "template": "{{text}}"
          },
          "date": {
            "title": "Review date",
            "type": "string",
            "description": "Review submission timestamp",
            "template": "{{date}}"
          },
          "tripType": {
            "title": "Trip type",
            "type": "string",
            "description": "Traveler type reported by the reviewer",
            "template": "{{tripType}}"
          },
          "language": {
            "title": "Review language",
            "type": "string",
            "description": "Review language tag",
            "template": "{{language}}"
          },
          "author": {
            "title": "Author",
            "type": "string",
            "description": "Reviewer display name",
            "template": "{{author}}"
          },
          "authorLocation": {
            "title": "Author location",
            "type": "string",
            "description": "Reviewer hometown when published",
            "template": "{{authorLocation}}"
          },
          "helpfulVotes": {
            "title": "Helpful votes",
            "type": "string",
            "description": "Helpful votes on the review",
            "template": "{{helpfulVotes}}"
          }
        },
        "required": [
          "recordType",
          "sourceUrl",
          "scrapedAt",
          "id"
        ]
      },
      "dockerfile": "../Dockerfile",
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "title": "Tripadvisor places and reviews",
          "views": {
            "overview": {
              "title": "All records",
              "transformation": {
                "fields": [
                  "recordType",
                  "name",
                  "title",
                  "type",
                  "rating",
                  "reviewCount",
                  "ranking",
                  "address",
                  "author",
                  "date",
                  "sourceUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "recordType": {
                    "label": "Record",
                    "format": "text"
                  },
                  "name": {
                    "label": "Place",
                    "format": "text"
                  },
                  "title": {
                    "label": "Review title",
                    "format": "text"
                  },
                  "type": {
                    "label": "Type",
                    "format": "text"
                  },
                  "rating": {
                    "label": "Rating",
                    "format": "number"
                  },
                  "reviewCount": {
                    "label": "Reviews",
                    "format": "number"
                  },
                  "ranking": {
                    "label": "Ranking",
                    "format": "text"
                  },
                  "address": {
                    "label": "Address",
                    "format": "text"
                  },
                  "author": {
                    "label": "Author",
                    "format": "text"
                  },
                  "date": {
                    "label": "Date",
                    "format": "text"
                  },
                  "sourceUrl": {
                    "label": "Source",
                    "format": "link"
                  }
                }
              }
            },
            "places": {
              "title": "Places",
              "transformation": {
                "fields": [
                  "id",
                  "name",
                  "type",
                  "rating",
                  "reviewCount",
                  "ranking",
                  "priceRange",
                  "cuisine",
                  "phone",
                  "email",
                  "address",
                  "amenities",
                  "photos",
                  "url"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "id": {
                    "label": "Place ID",
                    "format": "text"
                  },
                  "name": {
                    "label": "Name",
                    "format": "text"
                  },
                  "type": {
                    "label": "Type",
                    "format": "text"
                  },
                  "rating": {
                    "label": "Rating",
                    "format": "number"
                  },
                  "reviewCount": {
                    "label": "Reviews",
                    "format": "number"
                  },
                  "ranking": {
                    "label": "Ranking",
                    "format": "text"
                  },
                  "priceRange": {
                    "label": "Price",
                    "format": "text"
                  },
                  "cuisine": {
                    "label": "Cuisine",
                    "format": "text"
                  },
                  "phone": {
                    "label": "Phone",
                    "format": "text"
                  },
                  "email": {
                    "label": "Email",
                    "format": "text"
                  },
                  "address": {
                    "label": "Address",
                    "format": "text"
                  },
                  "amenities": {
                    "label": "Amenities",
                    "format": "text"
                  },
                  "photos": {
                    "label": "Photos",
                    "format": "text"
                  },
                  "url": {
                    "label": "Tripadvisor URL",
                    "format": "link"
                  }
                }
              }
            },
            "reviews": {
              "title": "Reviews",
              "transformation": {
                "fields": [
                  "id",
                  "placeId",
                  "title",
                  "rating",
                  "date",
                  "tripType",
                  "language",
                  "author",
                  "authorLocation",
                  "helpfulVotes",
                  "sourceUrl"
                ]
              },
              "display": {
                "component": "table",
                "properties": {
                  "id": {
                    "label": "Review ID",
                    "format": "text"
                  },
                  "placeId": {
                    "label": "Place ID",
                    "format": "text"
                  },
                  "title": {
                    "label": "Title",
                    "format": "text"
                  },
                  "rating": {
                    "label": "Rating",
                    "format": "number"
                  },
                  "date": {
                    "label": "Date",
                    "format": "text"
                  },
                  "tripType": {
                    "label": "Traveler type",
                    "format": "text"
                  },
                  "language": {
                    "label": "Language",
                    "format": "text"
                  },
                  "author": {
                    "label": "Author",
                    "format": "text"
                  },
                  "authorLocation": {
                    "label": "Author location",
                    "format": "text"
                  },
                  "helpfulVotes": {
                    "label": "Helpful votes",
                    "format": "number"
                  },
                  "sourceUrl": {
                    "label": "Source",
                    "format": "link"
                  }
                }
              }
            }
          }
        }
      },
      "readme": "# TripAdvisor Hotel, Restaurant & Attraction Finder\r\n\r\nRead Tripadvisor places and reviews in one actor. Search a destination for ranked hotels, restaurants and attractions, open a specific place by its Tripadvisor URL or numeric ID, or export a review stream with server-side filters. Everything works without a Tripadvisor account, API key or cookie.\r\n\r\n## Modes\r\n\r\n| Mode | What it does | Main inputs |\r\n|---|---|---|\r\n| `search` | Finds ranked places through Tripadvisor listing pages. If those pages are unavailable, it falls back to the GraphQL type-ahead index. | `query`, optional `location` |\r\n| `details` | Reads one place per URL or ID from the place page JSON-LD and embedded data, including amenities and a larger photo when published. | `startUrls` |\r\n| `reviews` | Reads reviews for each target place, 20 per request, with offset pagination and filters. Targets can come from URLs, IDs, or a search query. | `startUrls` or `query`, review filters |\r\n\r\nEvery record is a flat JSON object. Place rows carry `recordType: \"place\"`, review rows carry `recordType: \"review\"`, and both include `sourceUrl` and `scrapedAt`. Empty fields are omitted at every depth, so there are no nulls, empty strings, empty arrays or empty objects in the dataset.\r\n\r\n## Place fields\r\n\r\nCurrent fields: `id`, `name`, `type`, `url`, `ratingValue`, `reviewCount`, `ranking`, `priceRange`, `cuisine`, `phone`, `email`, `address`, `lat`, `lng`, `amenities`, `photos`, `sourceUrl`, `scrapedAt`, `recordType`, `detailSource`, `detailStatus`.\r\n\r\nBackward-compatible legacy fields are always restored on place rows: `locationId`, `subcategory`, `street`, `city`, `state`, `country`, `postalCode`, `latitude`, `longitude`, `rating`, `numberOfReviews`, `rankingPosition`, `rankingString`, `priceLevel`, `website`, `hotelClass`, `hours`, `description`, `neighborhoods`, `webUrl`, `isClosed`, `photoUrl`, `searchQuery`, `scrapeTimestamp`.\r\n\r\n`type` is `hotel`, `restaurant` or `attraction`. `ratingValue`, `reviewCount`, `lat` and `lng` are numeric. The legacy `rating`, `numberOfReviews`, `latitude` and `longitude` fields are strings, matching the pre-revamp contract. `amenities` and `photos` are arrays of strings. `ranking` is the full Tripadvisor ranking text when the place page publishes it.\r\n\r\nA TypeAhead fallback row carries `detailSource: \"typeaheadFallback\"` and `detailStatus: \"partial\"`; a normal detail-page row carries `detailStatus: \"complete\"`. Media URLs are checked for scheme, host and extension before they are published.\r\n\r\n## Review fields\r\n\r\n`id`, `placeId`, `title`, `text`, `rating`, `date`, `tripType`, `language`, `author`, `authorLocation`, `helpfulVotes`, `sourceUrl`, `scrapedAt`, `recordType`.\r\n\r\n`date` is the review submission timestamp, `tripType` is the traveler type reported by the reviewer, and `authorLocation` is the reviewer's published hometown.\r\n\r\n## Input\r\n\r\n| Field | Type | Default | Description |\r\n|---|---|---|---|\r\n| `mode` | select | `search` | `search`, `details` or `reviews`. |\r\n| `query` | string | - | Search phrase, for example `hotels in New York` or `Eiffel Tower`. Also used by `reviews` when no URLs are given. |\r\n| `location` | string | - | Optional destination for search, for example `New York`. With this set, `query` can be just `hotels`. |\r\n| `startUrls` | string list | - | Tripadvisor place URLs or numeric location IDs. Used by `details` and `reviews`. |\r\n| `maxItems` | integer 1-500 | `20` | Maximum places to return in `search`, process in `details`, or use as review targets in `reviews`. |\r\n| `includeDetails` | boolean | `true` | Fetch extra place data: key amenities, a larger photo, and HTML enrichment when the JSON fields are missing. |\r\n| `maxReviews` | integer 1-500 | `20` | Reviews per place in `reviews` mode. |\r\n| `reviewSort` | select | `MOST_RECENT` | `MOST_RECENT`, `MOST_HELPFUL` or `DETAILED`. Attractions automatically use `DETAILED` for `MOST_RECENT` so bookable product reviews do not mix into the attraction's reviews. |\r\n| `reviewRating` | select | `ANY` | `ANY` or 1-5. |\r\n| `reviewLanguage` | select | `ANY` | Common Tripadvisor language tags such as `en`, `de`, `fr` or `es`. |\r\n| `reviewTripType` | select | `ANY` | `FAMILY`, `COUPLES`, `SOLO`, `BUSINESS` or `FRIENDS`. |\r\n| `reviewMonth` | select | `ANY` | `JANUARY` through `DECEMBER`. |\r\n| `reviewKeyword` | string | - | Text that must appear in the review. |\r\n| `proxyConfiguration` | object | - | Optional. Direct access is tried first. |\r\n\r\nAt least one search phrase or start URL is required, depending on the mode. Search and details modes need their own target. Reviews mode accepts either start URLs or a query.\r\n\r\n## Examples\r\n\r\nOpen one hotel and include amenities:\r\n\r\n```json\r\n{\r\n  \"mode\": \"details\",\r\n  \"startUrls\": [\r\n    \"https://www.tripadvisor.com/Hotel_Review-g60763-d675616-Reviews-The_Plaza_New_York_A_Fairmont_Managed_Hotel-New_York_City_New_York.html\"\r\n  ],\r\n  \"maxItems\": 1,\r\n  \"includeDetails\": true\r\n}\r\n```\r\n\r\nSearch hotels in New York:\r\n\r\n```json\r\n{\r\n  \"mode\": \"search\",\r\n  \"query\": \"hotels\",\r\n  \"location\": \"New York\",\r\n  \"maxItems\": 10,\r\n  \"includeDetails\": false\r\n}\r\n```\r\n\r\nExport recent five-star English reviews for a place:\r\n\r\n```json\r\n{\r\n  \"mode\": \"reviews\",\r\n  \"startUrls\": [\"675616\"],\r\n  \"maxItems\": 1,\r\n  \"maxReviews\": 100,\r\n  \"reviewSort\": \"MOST_RECENT\",\r\n  \"reviewRating\": \"5\",\r\n  \"reviewLanguage\": \"en\"\r\n}\r\n```\r\n\r\nSearch a city and then export its reviews:\r\n\r\n```json\r\n{\r\n  \"mode\": \"reviews\",\r\n  \"query\": \"restaurants in Paris\",\r\n  \"maxItems\": 5,\r\n  \"maxReviews\": 20\r\n}\r\n```\r\n\r\n## How search works\r\n\r\nThe actor resolves the destination with the type-ahead GraphQL index and always sends the full free-text query first, even when the query contains a family word such as `restaurants`. Queries like `sushi restaurants in New York` therefore keep `sushi` in the request instead of browsing every restaurant in the city.\r\n\r\nRanked listing pages (`Hotels`, `Restaurants` and `Attractions`) 30 places at a time are used as a supplement. When listing rows are added for a free-text query, they are filtered client-side by the remaining terms against name, cuisine and description; unrelated rows are dropped and reported as `relevance_filtered` in the run status. TypeAhead results are limited to 20 per request, so a free-text-only query can stop at 20 rows; listing supplement and pagination extend family searches up to `maxItems`.\r\n\r\nDuplicates are removed by place ID, and TypeAhead results keep their order ahead of listing supplements. `search` never uses a browser, a cookie or a login. Listing pages use a Safari TLS profile; the JSON APIs are called with plain HTTP. With `includeDetails: true`, each place is opened once to fill the full ranking, amenities and photo.\r\n\r\n## How details works\r\n\r\nPlace IDs are read from URLs such as `/Hotel_Review-g60763-d675616-...` or from numeric IDs. Each place page is read as HTML and its schema.org JSON-LD plus server-rendered data supply the place fields, including rating, review count, ranking, price range, contacts, coordinates, amenities, cuisine and photos.\r\n\r\nWhen only a numeric ID is given, the actor opens a category-agnostic Tripadvisor URL and follows the canonical redirect to the hotel, restaurant or attraction page. Redirected URLs are accepted when they keep the same location ID; a redirect to a different ID or to a category page is treated as not found, so data is never attributed to the wrong place.\r\n\r\nIf a detail page is blocked, details mode falls back to the public TypeAhead record for the same location ID, including ID-only targets with no URL. The fallback is attempted even when the only target is a numeric ID. If TypeAhead cannot identify the place, the review clients resolve the type as a last resort (`detailSource: \"reviewTypeFallback\"`). Those rows are marked `detailStatus: \"partial\"` and counted as `details_fallback` in the run status. For reviews, an ID-only target whose detail page cannot resolve the place type also tries the three review clients before the run is marked blocked.\r\n\r\nUnsupported Tripadvisor entities such as activities, cruises and airlines are skipped with a counter instead of failing the whole run.\r\n\r\n## How reviews works\r\n\r\nReviews come from the public reviews GraphQL endpoint. Each request returns at most 20 reviews; the actor pages by offset until `maxReviews`, the place total, or the run cap is reached. Filters are sent to the server, not applied after downloading everything.\r\n\r\nUnlike many review tools, the actor filters every row by the target location ID. Attractions are read with the `DETAILED` sort when `MOST_RECENT` is requested, which keeps bookable product reviews out of the attraction's own review stream.\r\n\r\n## Limits\r\n\r\n- 20 results per TypeAhead request. Free-text-only queries can therefore stop at 20 unless listing pages add relevant rows.\r\n- Search listing pages hold 30 places; up to 17 pages (500 places) are read per family, matching the `maxItems` ceiling.\r\n- 500 reviews per place per run (a product cap; the upstream offset pagination was verified past 5,000).\r\n- 10,000 reviews per run across all targets.\r\n- 500 places per run.\r\n- Reviews are deduplicated by review ID and places by location ID.\r\n- Media URLs are validated for scheme, host and extension, but are not rehosted; a hotlink-blocked CDN URL can still fail in a consumer application.\r\n\r\nThe actor fails the run when it produces zero records or when every request is blocked. If only some targets or pages fail, it pushes the records it has and reports the partial counts in the run status, including `details_fallback` and `relevance_filtered`.\r\n\r\n## Proxy and anti-bot behaviour\r\n\r\nAccess is direct first. If Tripadvisor returns a real block, the actor tries the free Apify datacenter proxy (`AUTO`). It only moves to the `RESIDENTIAL` group after `AUTO` is also blocked. A user-supplied `proxyConfiguration` is used after a direct block. You do not need to configure anything for a normal run.\r\n\r\nEscalation is per request: every JSON or HTML request starts at `direct` and only that request moves up the ladder after a block. A blocked detail page therefore does not force later TypeAhead or review requests onto a paid rung.\r\n\r\nThe TypeAhead and reviews GraphQL endpoints are the primary path for discovery and reviews. Place details are read from the place page HTML, which is fetched with the Safari TLS profile and only when a place record is needed.\r\n\r\n## FAQ\r\n\r\n**Do I need a Tripadvisor account or API key?**\r\nNo. The actor reads public place and review data. It does not log in, and it does not need user cookies.\r\n\r\n**Do I need a proxy?**\r\nNo. Direct access is tried first and works for the JSON APIs. The actor escalates automatically only after a block.\r\n\r\n**Why is `amenities` missing for some places?**\r\nTripadvisor publishes amenities mainly for hotels. Restaurants and attractions often have none, and the field is omitted rather than filled with a placeholder.\r\n\r\n**Why are there fewer reviews than the total on the page?**\r\nThe review count on a place page can include reviews in many languages and, for attractions, reviews from bookable products. The actor returns the reviews that match the target place and your filters, up to `maxReviews`.\r\n\r\n**Why does a search return fewer places than `maxItems`?**\r\nTripadvisor may not render enough ranked cards for a destination, a page may be unavailable, or a free-text TypeAhead query may return at most 20 rows. The actor supplements TypeAhead with filtered listing pages and reports `relevance_filtered`, `listing_failures` and other partial counts in the status message.\r\n\r\n**Are the records always the same shape?**\r\nNo. Empty fields are removed, so a restaurant row has `cuisine` while a hotel row may have `amenities`. Every record keeps the identity, source and timestamp fields.\r\n\r\n**Is this affiliated with Tripadvisor?**\r\nNo. This is an independent, third-party actor that reads publicly available Tripadvisor data. It is not affiliated with or endorsed by Tripadvisor.\r\n"
    },
    "buildNumber": "2.0.3",
    "imageDigest": "b68594d9fd86b811c97b61befdfc20b3e629279461332bfd1d7678e762ec4663",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "2.0"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.004015555555555555
    }
  }
}