# Gathern Rental Listings Scraper (`bovi/gathern-scraper`) Actor

Collect public Gathern rental listings in Saudi Arabia without logging in. Get prices, capacity, ratings, locations, photos, and features. Run with a city or public search URL. Pricing: $0.00785 per saved listing plus $0.00005 per Actor Start event.

- **URL**: https://apify.com/bovi/gathern-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Real estate, Travel, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.85 / 1,000 gathern rental listings scrapers

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Gathern Rental Listings Scraper

Collect public vacation-rental listings from Gathern’s public search data and listing details in Saudi Arabia, without logging in. On the Free plan, pricing is $0.00005 per Actor Start event plus $0.00785 per saved rental listing on Free.

- Extract rental titles, types, prices, service totals, capacities, ratings, and reviews.
- Compare rental prices and availability across Riyadh, Jeddah, and other searched cities.
- Build location datasets with cities, districts, coordinates, photos, and property features.
- Use descriptions, amenities, bedroom details, and cancellation fields for rental research and travel planning.
- Run city or public search-URL queries without logging in to Gathern; proxy use is optional.

### What you get

The Actor reads Gathern’s public search results and listing details. Source-backed fields are emitted only when Gathern provides a value. The Actor also calculates `price_per_guest_sar` when nightly price and positive capacity are available.

| Field or fields | Type | What it contains | Notes |
|---|---|---|---|
| `listingId`, `url`, `propertyTitle` | Integer; string | Listing identifier, Gathern listing URL, and property title | Required dataset fields |
| `unit_type`, `unit_type_id` | String; integer | Rental category and category ID | For example, apartment or chalet |
| `currency` | String | Listing currency | The Actor records `SAR` |
| `nightly_price`, `price_before_discount`, `total_price_with_services` | Number | Nightly, pre-discount, and service-inclusive prices | Values returned by the source |
| `price_per_guest_sar` | Number | Nightly price divided by capacity | Rounded to two decimals when calculated |
| `capacity` | Integer | Guest capacity |  |
| `bedrooms`, `master_beds`, `single_beds`, `bathrooms` | Integer | Bedroom, bed, and bathroom counts | Counts are extracted from listing data |
| `area_sqm` | Number | Property area in square metres |  |
| `rating`, `reviews_count`, `booking_count`, `views_count` | Number; integer | Rating, reviews, bookings, and views |  |
| `city`, `city_ar`, `district`, `district_ar` | String | English and Arabic location names |  |
| `latitude`, `longitude` | Number | Geographic coordinates |  |
| `photos`, `thumbnail` | Array; string | Photo URLs and thumbnail URL |  |
| `features` | Array of strings | Property features and amenities |  |
| `description` | String | Listing description |  |
| `check_in`, `check_out` | String | Selected stay dates returned by Gathern |  |
| `available` | Boolean | Availability value returned by Gathern |  |
| `has_insurance`, `has_free_cancellation` | Boolean | Insurance and free-cancellation values |  |
| `scraped_at` | String | UTC timestamp for record creation |  |

### Sample output

The sample is shortened by omitting minor fields; the values shown are copied exactly from one dataset record.

```json
{
  "listingId": 277640,
  "url": "https://gathern.co/link/view?id=277640",
  "propertyTitle": "Apartment with Living Room",
  "unit_type": "Apartment",
  "currency": "SAR",
  "nightly_price": 300,
  "price_before_discount": 300,
  "total_price_with_services": 378,
  "price_per_guest_sar": 150,
  "capacity": 2,
  "rating": 10,
  "reviews_count": 1,
  "city": "Riyadh",
  "district": "Al Ghadeer Dist.",
  "latitude": 24.77799890874,
  "longitude": 46.661205478135
}
```

### Pricing

This Actor charges per event. Charges are based on the following events:

| Event | When it applies | Free-plan price |
|---|---|---:|
| `apify-actor-start` | When the Actor starts running | $0.00005 per event on the Free plan |
| `apify-default-dataset-item` | One scraped result with all fields; one saved rental listing is one dataset item | $0.00785 per event on the Free plan |

The number of Actor Start events depends on Actor memory, with a minimum of one event. A run with one Actor Start event and 50 saved results costs:

**50 results = $0.39255 on Free**\
`(50 × $0.00785) + $0.00005 = $0.39255 on Free`

With one Actor Start event, the Free-plan calculations are:

**1,000 results = $7.85005 on Free**\
`(1,000 × $0.00785) + $0.00005 = $7.85005 on Free`

**10,000 results = $78.50005 on Free**\
`(10,000 × $0.00785) + $0.00005 = $78.50005 on Free`

The Apify Free plan includes $5 of monthly platform usage credit. With one Actor Start event, that credit covers exactly 636 saved results at the Free-plan event prices.

Platform usage such as compute, Apify Proxy traffic including residential traffic, and storage is included in the event prices and paid by the Actor developer. Buyers do not separately pay platform usage.

### How to use

1. **Choose** `byCity` to search named cities, or choose `bySearchUrl` to use public Gathern search-result URLs.
2. **Enter** one or more city names in `cities`, or add public Gathern `/search` URLs in `searchUrls`.
3. **Set** optional city-search filters such as `unitType`, `checkIn`, `checkOut`, `lang`, and `sort`.
4. **Limit** pagination with `maxPages` and the number of unique saved listings with `maxResults`.
5. **Configure** optional Apify proxy settings, or set `useApifyProxy` to `false` to connect directly.
6. **Repeat** the run through Apify Schedules, using daily scheduling as a starting point for rental listings.

Example input:

```json
{
  "searchMode": "byCity",
  "cities": ["Riyadh"],
  "unitType": "chalet",
  "lang": "en",
  "maxResults": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

Export the dataset as JSON or CSV, or read it through the Apify dataset API.

### Input parameters

| Parameter | What it does | Default |
|---|---|---|
| `searchMode` | Selects `byCity` or `bySearchUrl`. | `byCity` |
| `cities` | City names used in city mode. English and Arabic names are accepted. | `["Riyadh"]` |
| `searchUrls` | Public Gathern search URLs used in search-URL mode. Gathern `/search` URLs and supported query parameters are processed. | Not set |
| `unitType` | Optional rental category for city searches: `resort`, `chalet`, `istraha`, `farm`, `camp`, `apartment`, `villa`, `room`, `studio`, or `serviced-apartment`. | `""` |
| `checkIn` | Optional city-search check-in date in `YYYY-MM-DD` format. | Not set |
| `checkOut` | Optional city-search check-out date in `YYYY-MM-DD` format. | Not set |
| `lang` | Selects `en` or `ar` for text returned by Gathern. | `en` |
| `sort` | Sorts city searches by `points`, `price`, `rate`, or `newest`. | `points` |
| `maxPages` | Maximum number of search pages processed for each city or URL. Must be at least 1. | `20` |
| `maxResults` | Maximum number of unique rental listings saved across the run. Must be at least 1. | `50` |
| `proxyConfiguration` | Optional Apify proxy settings. The schema default uses `useApifyProxy: true` with the `RESIDENTIAL` group; set it to false or leave it empty to connect directly. | Apify proxy with `RESIDENTIAL` |

### Limits and edge cases

| Condition | What the buyer sees | What to do |
|---|---|---|
| `maxResults` is reached | The Actor stops saving listings after the configured number of unique results across the run. | Increase `maxResults` for a larger dataset. |
| `maxPages` is reached | Pagination stops for that city or search URL even if more pages may exist. | Increase `maxPages`, which has a minimum of 1. |
| A search page returns no items or the source page count is reached | Pagination stops for that target. | Check the city, URL, dates, and filters, then run again if needed. |
| A search URL is not a public Gathern `/search` page | The URL is ignored and contributes no listings. | Use a public Gathern search-results URL. |
| A URL contains unsupported search parameters | Unsupported parameters are not translated into the search request. | Use filters represented by the supported Gathern search URL. |
| Gathern does not provide a field value | That field is omitted from the dataset record. | Use the fields available for each listing rather than expecting every record to have every field. |
| A search request fails on a target | A warning is logged and processing stops for that target; records already saved remain in the dataset. | Review the input and proxy configuration, then retry the run. |
| A listing-detail request fails | A warning is logged. A valid search result can still be saved, but detail fields may be absent; incomplete records without a listing ID or property title are skipped. | Retry the run if detail fields are needed. |
| The same listing appears in multiple targets | The Actor skips duplicate listing IDs and saves unique listings. | Use multiple targets when useful, while allowing for deduplication. |

### FAQ

#### How much does it cost to scrape Gathern rental listings?

On the Free plan, an Actor Start event costs $0.00005; each saved rental listing costs $0.00785 on Free. With one Actor Start event, 50 results = $0.39255 on Free.

#### Why did my run return no listings?

The Actor stops when a search response contains no items. A search URL may also be ignored if it is not a public Gathern `/search` page. Check the city or URL, dates, rental type, supported filters, and pagination limit.

#### What happens if Gathern access or a page fails?

A failed search request produces a warning and stops the current target, while records already saved remain available. If a detail request fails, the Actor can still save a valid search result, but fields supplied only by the detail response may be missing.

#### Is using public Gathern data legal or allowed?

The Actor reads Gathern’s public search data and listing details without logging in. Whether a particular use is legal or allowed depends on Gathern’s source terms and applicable law for your use case; review them before using the data.

### Related actors

- [Airbnb Scraper — Listings, Prices, Ratings & Hosts](https://apify.com/bovi/airbnb-scraper) — related bovi Actor for Airbnb listings, prices, ratings, and hosts.
- [At Home Japan Rental Listings](https://apify.com/bovi/athome-scraper) — related bovi Actor for rental listings.
- [Chaves na Mão Property Listings](https://apify.com/bovi/chaves-scraper) — related bovi Actor for property listings.

# Actor input Schema

## `searchMode` (type: `string`):

Choose named cities or provide Gathern search URLs.

## `cities` (type: `array`):

City names in English or Arabic, such as Riyadh, Jeddah, or الرياض. Used in City names mode.

## `searchUrls` (type: `array`):

Public Gathern search result URLs. Their city, dates, categories, and filters are preserved.

## `unitType` (type: `string`):

Optional rental category for City names mode.

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

Optional check-in date in YYYY-MM-DD form.

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

Optional check-out date in YYYY-MM-DD form.

## `lang` (type: `string`):

Language for text returned by Gathern.

## `sort` (type: `string`):

Sort city searches by Gathern's points, price, rating, or newest order.

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

Stops pagination after this many search pages for each city or URL.

## `maxResults` (type: `integer`):

Maximum number of unique rental listings to save.

## `proxyConfiguration` (type: `object`):

Optional Apify proxy settings. Leave disabled or empty to connect directly.

## Actor input object example

```json
{
  "searchMode": "byCity",
  "cities": [
    "Riyadh",
    "Jeddah"
  ],
  "searchUrls": [
    "https://gathern.co/search?city=3&chalet_cats%5B%5D=2"
  ],
  "unitType": "",
  "checkIn": "2026-11-01",
  "checkOut": "2026-11-03",
  "lang": "en",
  "sort": "points",
  "maxPages": 20,
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset with the scraped records.

# 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 = {
    "searchMode": "byCity",
    "cities": [
        "Riyadh"
    ],
    "lang": "en",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/gathern-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 = {
    "searchMode": "byCity",
    "cities": ["Riyadh"],
    "lang": "en",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/gathern-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 '{
  "searchMode": "byCity",
  "cities": [
    "Riyadh"
  ],
  "lang": "en",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call bovi/gathern-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bovi/gathern-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/pZxSXisssF6gut3K4/builds/s36Mh1SVa81M5RUfd/openapi.json
