# Wego Scraper - MENA Hotel Deals, Rates & Reviews (`abotapi/wego-com-scraper`) Actor

Scrape Wego hotels by city or search URL. Get rates, providers, booking links, coordinates, scores, images and property details. Optionally fetch guest review text, ratings, dates and public author details.

- **URL**: https://apify.com/abotapi/wego-com-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 hotel records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Wego Hotel Scraper

Find Wego hotel rates by city and stay dates, or paste hotel search links. Each dataset row contains a hotel, its cheapest available rate for that stay, and links to the hotel and booking offer. Optional profile and guest review fields add more detail when you need them.

### Why This Scraper?

- Search multiple cities or use Wego hotel search links with your chosen dates and guests.
- Compare quoted amounts, taxes, providers, room types and cancellation terms.
- Get location, star class, review scores and the image URLs available with each result.
- Add hotel contact details, amenities, policies and property information with `fetchDetails`.
- Add guest review text, ratings, dates and public author details with `fetchReviews`.
- Track changes across scheduled runs or resume an interrupted run without repeating earlier rows.

### Data You Get

| Field | Example |
|---|---|
| `hotelId` | `000001` |
| `name` | `Sample City Hotel` |
| `url` | Wego hotel page link |
| `star` | `4` |
| `cityName` | `Dubai` |
| `latitude` | `25.0000` |
| `longitude` | `55.0000` |
| `imageUrl` | Primary hotel image URL |
| `imageUrls` | Every image URL available with the result |
| `imagesCount` | `50`, the reported image count, which may exceed available URLs |
| `reviewScore` | `85` out of 100 |
| `reviewCount` | `100` |
| `reviewBreakdown` | Scores and counts by guest group |
| `priceAmount` | `180` in the quoted currency |
| `priceCurrency` | `USD` |
| `totalAmountUsd` | `180` |
| `taxAmountUsd` | `20` |
| `providerCode` | `example-provider` |
| `roomType` | `Standard room` |
| `freeCancellation` | `true` |
| `address` | Available with `fetchDetails` |
| `amenities` | Available with `fetchDetails` |
| `reviews` | Guest reviews when `fetchReviews` is on |
| `reviewsFetched` | Number of guest reviews returned for this hotel |

### How to Use

#### Search a city

```json
{
  "mode": "search",
  "locations": ["Dubai"],
  "checkIn": "2026-10-01",
  "checkOut": "2026-10-03",
  "maxItems": 20
}
```

#### Compare several cities with filters

```json
{
  "mode": "search",
  "locations": ["Dubai", "Doha"],
  "checkIn": "2026-10-01",
  "checkOut": "2026-10-03",
  "starRatings": ["4", "5"],
  "maxPriceUsd": 300,
  "maxItems": 30
}
```

#### Fetch hotel profiles and guest reviews

```json
{
  "mode": "search",
  "locations": ["Dubai"],
  "checkIn": "2026-10-01",
  "checkOut": "2026-10-03",
  "fetchDetails": true,
  "fetchReviews": true,
  "maxReviewsPerHotel": 20,
  "maxItems": 5
}
```

#### Use hotel search links

```json
{
  "mode": "url",
  "urls": ["https://www.wego.com/en/hotels/searches/dxb/2026-10-01/2026-10-03?guests=2"],
  "maxItems": 20
}
```

Hotel detail page links are not accepted as input. Results and prices depend on availability for the selected stay. `imageUrls` contains URLs supplied with the result; `imagesCount` is a separate reported count.

### Input Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | Search by city or use `url` for hotel search links. |
| `locations` | array | `Dubai` | City names in search mode. |
| `checkIn` | string | next available date | Stay start in search mode. |
| `checkOut` | string | day after check-in | Stay end in search mode. |
| `rooms` | integer | `1` | Rooms in search mode. |
| `adults` | integer | `2` | Adults in search mode. |
| `currency` | string | `USD` | Currency for quoted rates. |
| `urls` | array | example search link | Wego hotel search links in URL mode. |
| `starRatings` | array | none | Keep selected star classes. |
| `minPriceUsd` | integer | none | Minimum quoted price in USD. |
| `maxPriceUsd` | integer | none | Maximum quoted price in USD. |
| `freeCancellationOnly` | boolean | `false` | Keep offers with free cancellation. |
| `sortBy` | string | `popularity` | Order returned hotels. |
| `fetchDetails` | boolean | `true` | Add the hotel profile. One enrichment event per committed profile. |
| `fetchReviews` | boolean | `false` | Add guest review records. |
| `maxReviewsPerHotel` | integer | `20` | Review cap per hotel; `0` skips review reads. |
| `maxItems` | integer | `20` | Maximum hotel rows; `0` means unlimited. |
| `maxPages` | integer | `0` | Maximum feed polls per city; `0` means no user-set poll limit. |
| `resumeFromRunId` | string | none | Continue from an earlier run or dataset. |
| `incrementalMode` | boolean | `false` | Return changes for a recurring search. |
| `stateKey` | string | none | Optional name for the recurring search state. |
| `emitUnchanged` | boolean | `false` | Also return unchanged hotels. |
| `emitExpired` | boolean | `false` | Also return hotels absent after a complete scan. |
| `mcpConnectors` | array | empty | Optional connector IDs for an export. |
| `notionParentPageUrl` | string | none | Parent page for a Notion export. |
| `maxNotifyListings` | integer | `50` | Maximum rows sent through connectors. |
| `proxy` | object | Apify default | Connection configuration. |

The hotel record is charged once per dataset row. A successful profile read adds one Hotel detail enrichment event. When guest reviews are enabled, each started block of 10 fetched reviews adds one more enrichment event on a hotel row that is returned: 1-10 reviews add one event, 11-20 add two. Empty or failed review reads and unchanged rows suppressed by incremental mode add no review event.

For recurring monitoring, keep the same city, stay dates and filters. The first incremental run returns NEW hotels; later runs return changes. `emitUnchanged` and `emitExpired` can add billed rows. Resume continues a specific previous run and skips rows it already collected.

### Send results into your apps (MCP connectors)

Optionally select authorized connectors with `mcpConnectors`. Set `notionParentPageUrl` for Notion and use `maxNotifyListings` to cap exported rows. The complete records remain in the dataset.

### Output Example

> Sample shape: values are illustrative placeholders, not from a live hotel.

```json
{
  "recordId": "000001",
  "hotelId": 1,
  "rowType": "hotel",
  "name": "Sample City Hotel",
  "url": "https://www.wego.com/en/hotels/searches/dxb/2026-10-01/2026-10-03/1",
  "star": 4,
  "cityCode": "DXB",
  "cityName": "Dubai",
  "latitude": 25.0,
  "longitude": 55.0,
  "imageUrl": "https://zen.wego.com/hotelz/000/00000000/0000000000.jpeg",
  "imageUrls": ["https://zen.wego.com/hotelz/000/00000000/0000000000.jpeg"],
  "imagesCount": 10,
  "reviewScore": 85,
  "reviewCount": 100,
  "priceAmount": 180,
  "priceCurrency": "USD",
  "priceUsd": 180,
  "providerCode": "example-provider",
  "roomType": "Standard room",
  "freeCancellation": true,
  "address": "Sample street, Dubai",
  "amenities": ["Wi-Fi", "Parking"],
  "reviewsFetched": 1,
  "reviews": [{"reviewId": "review-0001", "rating": 8, "comments": [{"type": "pros", "comment": "Comfortable room"}], "postedAt": "2026-01-01", "authorName": "Guest Name"}],
  "changeType": "NEW",
  "changedFields": [],
  "firstSeenAt": "2026-01-01T00:00:00Z",
  "lastSeenAt": "2026-01-01T00:00:00Z"
}
```

The sample shows optional profile and guest review fields together. Search-only runs omit profile fields, and reviews are included only when enabled.

### Plan Requirement

An Apify account is needed to run the actor. Choose review and detail options based on the data you need; the input shows the charges associated with each option.

# Actor input Schema

## `mode` (type: `string`):

How to start the scrape. 'search' runs the site's own hotel metasearch for the cities and stay window you set. 'url' processes the Wego hotels search URLs you paste: each URL's own path decides the city and dates, so the search-mode fields below do not apply there.

## `locations` (type: `array`):

One or more city names, for example 'Dubai', 'Makkah', 'Cairo', 'Doha', 'Abu Dhabi'. Each name is matched against the site's own place search; a name with no match is skipped with a warning, never invented. Search mode only: in URL mode the pasted URL decides its own scope.

## `checkIn` (type: `string`):

Stay window start, YYYY-MM-DD. Defaults to about a week from today when left empty. Search mode only.

## `checkOut` (type: `string`):

Stay window end, YYYY-MM-DD. Must be after the check-in date; defaults to two nights after check-in when left empty. Search mode only.

## `rooms` (type: `integer`):

Number of rooms to price, 1 to 4. Rates are quoted per room for the whole stay. Search mode only.

## `adults` (type: `integer`):

Adult guests per room, 1 to 8. Search mode only.

## `currency` (type: `string`):

Currency the rates are quoted in. The USD-converted price is always included on every row, so currency only changes the display values. Search mode only.

## `urls` (type: `array`):

Paste hotels search URLs like https://www.wego.com/en/hotels/searches/dxb/2026-10-01/2026-10-03?guests=2 (any city, dates and guests). Multi-URL supported; each is walked independently. Hotel detail page URLs are not supported in this version.

## `starRatings` (type: `array`):

Keep only hotels of these star classes. Empty means every class. Applied to the rows this run reads. Applies in BOTH modes.

## `minPriceUsd` (type: `integer`):

Only keep rows whose rate is at least this many US dollars for the whole stay. Applied to the rows this run reads. Applies in BOTH modes.

## `maxPriceUsd` (type: `integer`):

Only keep rows whose rate is at most this many US dollars for the whole stay. Applied to the rows this run reads. Applies in BOTH modes.

## `freeCancellationOnly` (type: `boolean`):

Keep only rows whose quoted rate carries a free-cancellation window in the source's own terms. Applied to the rows this run reads. Applies in BOTH modes.

## `sortBy` (type: `string`):

Arranges the rows this run collected, after they are read. 'As the site streamed them' keeps the source's own display order for your stay window. This is a local tidy up of one run's output, not a catalogue-wide ordering. Applies in BOTH modes.

## `fetchDetails` (type: `boolean`):

Read each hotel's own profile for the complete record: address, phone, email, website, description, named amenities, check-in and check-out times, room and floor counts, payment options and review highlights. The feed row already carries name, star class, coordinates, review score, cheapest rate, provider, room type, board basis and free-cancellation terms. Turning this on adds the Hotel detail enrichment charge per record actually enriched this run.

## `fetchReviews` (type: `boolean`):

Optionally read the latest guest reviews for each hotel. Off by default. The existing Hotel detail enrichment event adds one unit per started block of 10 reviews returned on a committed hotel row. Works with Fetch hotel details on or off; no review charge for zero reviews, failed reads or suppressed incremental rows.

## `maxReviewsPerHotel` (type: `integer`):

Maximum guest reviews to collect for each hotel when Fetch guest reviews is on. Reviews are read 10 at a time; 1-10 reviews add one enrichment unit, 11-20 add two, and so on. Set 0 to skip review reads.

## `maxItems` (type: `integer`):

The single cap on this run: stop after collecting this many records across all cities and URLs. Set 0 for unlimited.

## `maxPages` (type: `integer`):

Safety bound on how many times to re-poll the streaming results feed per city while it fills in. Leave empty (0) for no poll limit: the run then stops when the feed reports it is done, or at Max items, not here.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large crawl without returning or charging for records already collected there. Use this after an interrupted or capped run. For recurring monitoring of the same search, use Incremental mode below instead.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or weekly recurring monitoring of the same scope, for example a city rate watch. The first run returns everything matching as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. Rate moves ARE reported as UPDATED: on a metasearch the rate is the signal, not noise. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately per city, URL and filter setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the cities, URLs and filters, so two different scopes never mix state.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return records that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you specifically want a full snapshot every run.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return records that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked scope: not when Max items capped it, not when Resume was used, and not when the run was refused. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.

## `mcpConnectors` (type: `array`):

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 page per record; other connectors get a best-effort write or digest. Each connector receives a condensed summary per record, not the full record; the complete record always stays in the dataset. Leave empty to skip; this 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` (type: `string`):

URL or id of the Notion page under which record pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on records written to each connector per run. Does not affect the dataset.

## `proxy` (type: `object`):

Leave the default. Every read route on this source answers plain JSON to the standard shared pool, so the cheapest connection already works.

## Actor input object example

```json
{
  "mode": "search",
  "locations": [
    "Dubai"
  ],
  "rooms": 1,
  "adults": 2,
  "currency": "USD",
  "urls": [
    "https://www.wego.com/en/hotels/searches/dxb/2026-10-01/2026-10-03?guests=2"
  ],
  "freeCancellationOnly": false,
  "sortBy": "popularity",
  "fetchDetails": true,
  "fetchReviews": false,
  "maxReviewsPerHotel": 20,
  "maxItems": 20,
  "maxPages": 0,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxNotifyListings": 50,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "locations": [
        "Dubai"
    ],
    "rooms": 1,
    "adults": 2,
    "currency": "USD",
    "urls": [
        "https://www.wego.com/en/hotels/searches/dxb/2026-10-01/2026-10-03?guests=2"
    ],
    "freeCancellationOnly": false,
    "sortBy": "popularity",
    "fetchDetails": true,
    "fetchReviews": false,
    "maxReviewsPerHotel": 20,
    "maxItems": 20,
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/wego-com-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "locations": ["Dubai"],
    "rooms": 1,
    "adults": 2,
    "currency": "USD",
    "urls": ["https://www.wego.com/en/hotels/searches/dxb/2026-10-01/2026-10-03?guests=2"],
    "freeCancellationOnly": False,
    "sortBy": "popularity",
    "fetchDetails": True,
    "fetchReviews": False,
    "maxReviewsPerHotel": 20,
    "maxItems": 20,
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/wego-com-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "locations": [
    "Dubai"
  ],
  "rooms": 1,
  "adults": 2,
  "currency": "USD",
  "urls": [
    "https://www.wego.com/en/hotels/searches/dxb/2026-10-01/2026-10-03?guests=2"
  ],
  "freeCancellationOnly": false,
  "sortBy": "popularity",
  "fetchDetails": true,
  "fetchReviews": false,
  "maxReviewsPerHotel": 20,
  "maxItems": 20,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call abotapi/wego-com-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/wego-com-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/jTTZWCoEIDD3S5Ohq/builds/8NzVHTsnj2TlNSdse/openapi.json
