{
  "openapi": "3.0.1",
  "info": {
    "title": "Traveloka Hotel Scraper - SEA Hotel Prices & Ratings",
    "description": "Scrape Traveloka hotels across Singapore, Malaysia, Indonesia, Thailand, Vietnam and the Philippines: nightly prices, star ratings, guest scores, coordinates and photos by city. Paste search or hotel links, and monitor price changes with recurring updates.",
    "version": "0.1",
    "x-build-id": "xalkhJhxjeVsDuhWB"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~traveloka-com-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-traveloka-com-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/abotapi~traveloka-com-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-traveloka-com-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/abotapi~traveloka-com-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-traveloka-com-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Search walks hotel results for the locations below. URL mode pastes Traveloka hotel-search links (with spec=) or hotel detail links; search filters are ignored in URL mode.",
            "default": "search"
          },
          "market": {
            "title": "Market (site locale)",
            "enum": [
              "en-sg",
              "en-my",
              "en-id",
              "en-th",
              "en-vn",
              "en-ph",
              "en-au"
            ],
            "type": "string",
            "description": "Which Traveloka storefront to read. Sets the language and the currency prices are returned in.",
            "default": "en-sg"
          },
          "locations": {
            "title": "Cities or areas",
            "type": "array",
            "description": "City or area names as you would type them into Traveloka's hotel search box (e.g. Singapore, Bangkok, Kuta). Each location is resolved to Traveloka's internal region id, then its results are walked. Multiple locations are split evenly across your result budget.",
            "items": {
              "type": "string"
            }
          },
          "checkInDate": {
            "title": "Check-in date",
            "type": "string",
            "description": "Check-in date (YYYY-MM-DD). Leave empty to default to tomorrow (site time)."
          },
          "checkOutDate": {
            "title": "Check-out date",
            "type": "string",
            "description": "Check-out date (YYYY-MM-DD). Leave empty to default to the day after check-in."
          },
          "adults": {
            "title": "Adults",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Number of adult guests per search.",
            "default": 2
          },
          "rooms": {
            "title": "Rooms",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "Number of rooms per search.",
            "default": 1
          },
          "sortBy": {
            "title": "Sort results by",
            "enum": [
              "popularity",
              "price-asc",
              "price-desc"
            ],
            "type": "string",
            "description": "Search-mode sort order requested from the site. Popularity is Traveloka's own default order.",
            "default": "popularity"
          },
          "minPrice": {
            "title": "Min nightly price",
            "minimum": 0,
            "type": "integer",
            "description": "Drop hotels whose nightly price is below this. Applied to returned results (client side), in the market's currency."
          },
          "maxPrice": {
            "title": "Max nightly price",
            "minimum": 0,
            "type": "integer",
            "description": "Drop hotels whose nightly price is above this. Applied to returned results (client side), in the market's currency."
          },
          "minStarRating": {
            "title": "Min star rating",
            "type": "integer",
            "description": "Drop hotels below this star rating (0 = keep all). Applied to returned results (client side).",
            "default": 0
          },
          "minGuestRating": {
            "title": "Min guest score (0-10)",
            "minimum": 0,
            "maximum": 10,
            "type": "number",
            "description": "Drop hotels whose guest review score is below this (Traveloka scores out of 10). Applied to returned results (client side); hotels without a score are kept."
          },
          "urls": {
            "title": "Traveloka links",
            "type": "array",
            "description": "Multi-URL supported. Paste hotel-search links that contain spec= (from a browser search) and/or hotel detail links. Filter-mode fields are ignored; a search link walks forward from its own dates and occupancy.",
            "default": [
              "https://www.traveloka.com/en-sg/hotel/search?spec=01-12-2026.02-12-2026.1.1.HOTEL_GEO.107493.Singapore.2",
              "https://www.traveloka.com/en-sg/hotel/singapore/v-hotel-lavender-254056"
            ],
            "items": {
              "type": "string"
            }
          },
          "fetchDetails": {
            "title": "Enrich each hotel (facilities, features, images, ratings)",
            "type": "boolean",
            "description": "Merges the static-content feed into each row: facility codes + labels, feature highlights, extra images and UGC ratings. Each enriched row bills the detail-enrichment surcharge event once; unenriched rows push the base listing and bill nothing extra. A pasted hotel detail link is read as a page only when this is on; a link whose page cannot be read is skipped and not billed. With only Read guest reviews on, a link whose reviews cannot be read is skipped and not billed too.",
            "default": false
          },
          "fetchReviews": {
            "title": "Read guest reviews per hotel",
            "type": "boolean",
            "description": "Adds a reviews array (author, rating, date, text) from the review JSON lane, up to maxReviews per hotel. Rows with fetched reviews bill the detail-enrichment surcharge like other enrichment (search results: started blocks of 10 reviews, minimum 1; hotel detail links: 1 unit per row). Works with fetchDetails on or off.",
            "default": false
          },
          "maxReviews": {
            "title": "Max reviews per hotel",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on review rows per hotel when fetchReviews is on. Billing scales with volume: for search results each enriched row bills detail-enrichment units equal to the number of started blocks of 10 reviews, minimum 1 (10 reviews = 1, 25 = 3, 1000 = 100). A hotel detail link bills 1 unit per row.",
            "default": 10
          },
          "reviewSortBy": {
            "title": "Review order",
            "enum": [
              "DEFAULT",
              "SORT_CREATED_DESCENDING",
              "SORT_CREATED_ASCENDING",
              "SORT_HELPFUL_DESCENDING",
              "SORT_RATING_DESCENDING",
              "SORT_RATING_ASCENDING"
            ],
            "type": "string",
            "description": "Order of the reviews array when fetchReviews is on. The order is applied to the reviews read for each hotel (up to maxReviews); it does not search the site's whole review list for the best or newest ones.",
            "default": "DEFAULT"
          },
          "reviewCutoffDate": {
            "title": "Only reviews newer than",
            "type": "string",
            "description": "When fetchReviews is on, keep only reviews dated after this day (YYYY-MM-DD). Leave empty for no date filter."
          },
          "aggregateRatings": {
            "title": "Add aggregated rating",
            "type": "boolean",
            "description": "When fetchReviews is on, adds an aggregatedReview object (count, overallRating) to each hotel row. The data this actor reads carries no per-score breakdown.",
            "default": true
          },
          "maxItems": {
            "title": "Max results",
            "minimum": 0,
            "maximum": 100000,
            "type": "integer",
            "description": "The one real cap: maximum hotel records to return per run, across all locations. 0 means unlimited.",
            "default": 20
          },
          "maxPages": {
            "title": "Max pages per location",
            "minimum": 0,
            "type": "integer",
            "description": "Safety cap on result pages walked per location. 0 (default) means no page cap: the walk follows Max results and the site's own result count.",
            "default": 0
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "With the default RESIDENTIAL group the run starts on Apify residential with a multi-country pool (SG/ID/MY/TH/VN/PH, a fresh exit per attempt) and fails over to backup connections when every exit is refused. If you remove the RESIDENTIAL group the run starts on a datacenter lane, which the site usually refuses, and escalates to residential and then the backup connections. Free plans have no residential proxies: bring your own proxy URLs.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          },
          "resumeFromRunId": {
            "title": "Resume from run ID",
            "type": "string",
            "description": "ID of an interrupted run of this Actor to continue, skipping hotels already saved by that run. Leave empty for a fresh run. Conflicts with Incremental mode (pick one)."
          },
          "incrementalMode": {
            "title": "Incremental mode",
            "type": "boolean",
            "description": "Recurring monitoring: the Actor remembers hotels it saw on the previous run of the same scope and only emits new or changed ones. Rows carry changeType/changedFields. Unchanged rows are suppressed (set emitUnchanged to also emit and bill them). Conflicts with Resume from run ID.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional)",
            "type": "string",
            "description": "Name for the storage the incremental baseline is kept under. Leave empty to derive it from your scope (mode, market, locations, dates, occupancy and filters), so different setups never share a baseline."
          },
          "emitUnchanged": {
            "title": "Emit unchanged rows",
            "type": "boolean",
            "description": "With Incremental mode: also emit (and bill) rows whose fingerprint did not change, marked changeType UNCHANGED.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired rows",
            "type": "boolean",
            "description": "With Incremental mode: also emit (and bill) rows that were tracked before but no longer appeared in a complete walk, marked changeType EXPIRED. Never fires when the walk was capped, truncated or refused part-way.",
            "default": false
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Incremental mode only: field names that never make a hotel count as updated, for example price or guestRating. Use dots for nested fields. The fields are still kept in the output. The cover image link is always ignored because its address rotates between runs; hotel facilities are compared regardless of list order. Changing this list never re-bills the saved baseline.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify → Settings → API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write/digest. Leave empty to skip (never changes the dataset output). Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}