# Bookmundi Tours Search Scraper (`stealth_mode/bookmundi-tours-search-scraper`) Actor

Scrape tour listings from Bookmundi.com search pages and collect 50+ fields per tour — including pricing, ratings, destinations, tour types, operator info, and availability. Perfect for travel aggregators, analysts, and OTA developers.

- **URL**: https://apify.com/stealth_mode/bookmundi-tours-search-scraper.md
- **Developed by:** [Stealth mode](https://apify.com/stealth_mode) (community)
- **Categories:** Automation, Developer tools, Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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

## Bookmundi.com Tours Scraper: Extract Travel Tour Search Results

**Excerpt:** Scrape tour listings from Bookmundi.com search pages and collect 50+ fields per tour — including pricing, ratings, destinations, tour types, operator info, and availability. Perfect for travel aggregators, analysts, and OTA developers.

***

### What Is Bookmundi.com?

Bookmundi.com is a global tour booking platform aggregating thousands of multi-day trips, cruises, private tours, and adventure packages from operators worldwide. Its search results pages contain rich, structured tour data — but extracting it manually across hundreds of pages is impractical. The **Bookmundi Tours Search Scraper** automates this, turning search result pages into clean, structured datasets.

***

### Overview

This scraper targets Bookmundi's tour search and filter URLs, collecting detailed records for every listing on the page. It is well-suited for:

- **Travel aggregators** building or refreshing tour inventory feeds
- **Price monitoring tools** tracking discounts and rate changes
- **Market researchers** analyzing tour supply by destination or operator
- **OTA developers** integrating third-party tour data into booking platforms

***

### Input Format

The Actor supports **two scraping modes** — use only **one at a time**:

1. **Scrape by URLs** — scrape data directly from a list of Bookmundi search result URLs.

```json
{
  "urls": ["https://www.bookmundi.com/s/italy?page=10"],
  "ignore_url_failures": true,
  "max_items_per_url": 200
}
```

2. **Scrape by search filters** — scrape data using a keyword and additional filters (duration, price range, country, activity, etc.) instead of providing URLs.

```json
{
  "keyword": "helz",
  "duration": "7-162",
  "price_range": "3553-40999",
  "is_group_tour": true,
  "is_small_group_tour": true,
  "has_discount": true,    
  "country": "6a2fceb14e8381dd36d0c3b0",
  "activity": "6a2ffcd24e8381dd36d18605",
  "sort_by": "price",
  "page": 1,
  "max_items_per_url": 200
}

```

There is also a **General settings** group that applies to both modes.

#### 1. Scrape by URLs

Use this mode when you already have specific search result URLs. When this mode is used, all options in the "Scrape by search filters" section will be disabled.

| Field | Type | Default | Description |
|---|---|---|---|
| `urls` | `array` | — | Search result page URLs to scrape (e.g., `/s/italy?page=10`). You can paste URLs one by one, or use the Bulk edit section to add a prepared list. Add multiple URLs for multi-page or multi-query runs. |
| `ignore_url_failures` | `boolean` | `true` | If `true`, the scraper continues running when a URL fails, skipping it instead of stopping the entire run. |

> **Tip:** Use Bookmundi's filter parameters in the URL (destination, duration, price range, tour type) to target specific segments. Paginate with `?page=N` to collect across multiple pages.

#### 2. Scrape by search filters

Use this mode when you want to search using a keyword and additional filter attributes instead of scraping by URLs. If you use this mode, leave the `urls` field above empty.

| Field | Type | Default | Description |
|---|---|---|---|
| `keyword` | `string` | — | The keyword to search for. |
| `country` | `string` (select) | `""` (Any) | Filter tours by destination country, e.g. Italy, France, Spain, Nepal, Vietnam, Peru, and many others. |
| `activity` | `string` (select) | `""` (Any) | Filter tours by activity type, e.g. Trekking and Hiking, City sightseeing, Wildlife safaris, Beach, Cruise, Food tours, and many others. |
| `sort_by` | `string` (`""`, `price`, `duration`, `discount`) | — | Sort results by **Relevance** (empty), **Price**, **Duration**, or **Discount**. |
| `duration` | `string` | — | Trip duration range in days, in `min-max` format (e.g., `0-100`). |
| `price_range` | `string` | — | Price range, in `min-max` format (e.g., `0-1000`). |
| `is_group_tour` | `boolean` | `false` | If `true`, only include group tours. |
| `is_small_group_tour` | `boolean` | `false` | If `true`, only include small group tours. |
| `has_discount` | `boolean` | `false` | If `true`, only include tours with a discount. |
| `page` | `integer` | — | The page number to start scraping from. |

#### 3. General settings

Applies to both scraping modes above.

| Field | Type | Default | Description |
|---|---|---|---|
| `max_items_per_url` | `integer` | `20` | Maximum number of tour listings to collect per URL/search. Increase up to `200` for larger result sets. |

***

### Output Format

**Sample output**

```json
{
  "product_id": 4957,
  "product_title": "Journeys: Iconic Italy",
  "product_slug": "journeys-iconic-italy-4957",
  "featured_image": "/tour/iconic-italy-266137-1644387579.jpg",
  "search_image": "tour/iconic-italy-266137-1644387579.jpg",
  "is_multi_day_tour": true,
  "is_private_tour": false,
  "is_private_and_group_tour": false,
  "is_group_tour": true,
  "is_small_group_tour": true,
  "is_independent_tour": false,
  "is_cruise_tour": false,
  "is_eco_tour": true,
  "is_api_operator": true,
  "is_solo_tour": false,
  "is_single_country_tour": true,
  "is_multi_country_tour": false,
  "is_tour_customizable": false,
  "map_snapshot_image": "snapshots/df18f610-9511-4be5-8798-aea57271f1d9.jpeg",
  "min_age": 12,
  "max_age": 100,
  "duration": 14,
  "duration_type": "days",
  "duration_in_minutes": 20160,
  "start_destination": {
    "id": 243,
    "idx": "243:Venice",
    "city": "Venice",
    "country": "Italy",
    "country_id": 82
  },
  "end_destination": {
    "id": 215,
    "idx": "215:Rome",
    "city": "Rome",
    "country": "Italy",
    "country_id": 82
  },
  "countries": {
    "text": "italy",
    "idx": "82:Italy",
    "ids": [
      82
    ]
  },
  "tour_types": [
    201,
    2
  ],
  "destinations": {
    "ids": [
      215,
      243,
      961,
      13725,
      234,
      511,
      513
    ],
    "idx": "215:Rome;243:Venice:19380;961:Amalfi;13725:Cinque Terre:516;234:Florence:557;511:Naples:19381;513:Sorrento:19381",
    "text": "Rome;Venice;Amalfi;Cinque Terre;Florence;Naples;Sorrento"
  },
  "trip_language": "english",
  "guide_language": "english",
  "accommodations": [
    "Premium"
  ],
  "accommodation_labels": [
    "Hotel",
    "Villa"
  ],
  "activities": {
    "text": "Cultural, religious and historic sites;City sightseeing;Countryside and village visits;Museum and gallery visits;Farm and plantation visits",
    "ids": [
      1505,
      232,
      1497,
      607,
      1715
    ],
    "idx": "1505:Cultural, religious and historic sites:1818;232:City sightseeing:1818;1497:Countryside and village visits:1818;607:Museum and gallery visits:1818;1715:Farm and plantation visits:1814",
    "parent_idx": "1818:Sightseeing, attractions, culture and history;1814:Wildlife, landscapes and nature",
    "parent_ids": [
      1818,
      1818,
      1818,
      1818,
      1814
    ]
  },
  "continents": {
    "text": "europe",
    "idx": "3:Europe",
    "ids": [
      3
    ]
  },
  "description_text": "$76",
  "review_text": "G Adventures and Cinzia our CEO made traveling through Italy, easy, fun, with unforgettable memories. I highly recommend, and I plan to book another trip with G Adventures. Thank you Cinzia for making this trip AMAZING!",
  "product_has_discount": true,
  "rating_count": 8,
  "rating_score": 5,
  "is_best_seller": false,
  "is_selling_fast": false,
  "is_budget_tour": false,
  "is_luxury_tour": true,
  "physical_rating_level": "moderate",
  "tour_operator_id": 1156,
  "tour_operator": "G Adventures",
  "cutoff_days": 7,
  "default_region_code": null,
  "default_version_id": null,
  "available_regions": "",
  "original_price": 7099,
  "discounted_price": 5679,
  "discount_percentage": 20.002817298211017,
  "from_url": "https://www.bookmundi.com/s/italy?page=2"
}
```

Each tour listing returns a record with 50+ fields, grouped below by category.

#### Identity & Media

| Field | Meaning |
|---|---|
| `Product ID` | Unique Bookmundi identifier for the tour |
| `Product Title` | Display name of the tour |
| `Product Slug` | URL-safe version of the title |
| `Featured Image` | Primary image URL shown in listings |
| `Search Image` | Thumbnail used in search result cards |
| `Map Snapshot Image` | Static map preview of the tour route |

#### Tour Type Flags

Boolean fields that classify the tour's format. Each can be `true` or `false`:

| Field | Meaning |
|---|---|
| `Is Multi Day Tour` | Spans multiple days |
| `Is Private Tour` | Private group only |
| `Is Private And Group Tour` | Offers both private and group options |
| `Is Group Tour` | Shared/group departure |
| `Is Small Group Tour` | Capped group size |
| `Is Independent Tour` | Self-guided format |
| `Is Cruise Tour` | Cruise-based itinerary |
| `Is Eco Tour` | Eco/sustainable-certified tour |
| `Is Solo Tour` | Marketed to solo travelers |
| `Is API Operator` | Operator connected via API |

#### Geography

| Field | Meaning |
|---|---|
| `Start Destination` | Departure city/location |
| `End Destination` | Final arrival city/location |
| `Countries` | List of countries covered |
| `Destinations` | Specific destinations visited |
| `Continents` | Continent(s) the tour spans |
| `Is Single Country Tour` | Stays within one country |
| `Is Multi Country Tour` | Crosses multiple countries |
| `Default Region Code` | Primary region/currency region |

#### Duration & Logistics

| Field | Meaning |
|---|---|
| `Duration` | Human-readable duration (e.g., "7 days") |
| `Duration Type` | Unit type: days, hours, etc. |
| `Duration In Minutes` | Normalized duration for sorting/filtering |
| `Min Age` | Minimum participant age |
| `Max Age` | Maximum participant age |
| `Cutoff Days` | Booking cutoff before departure |
| `Trip Language` | Language the tour operates in |
| `Guide Language` | Language(s) spoken by guides |

#### Content & Experience

| Field | Meaning |
|---|---|
| `Description Text` | Full tour description (plain text) |
| `Review Text` | Aggregated or featured review snippet |
| `Tour Types` | Activity categories (e.g., hiking, cultural) |
| `Activities` | Specific activities included |
| `Accommodations` | Accommodation types (e.g., hotel, hostel) |
| `Accommodation Labels` | Labeled tiers (e.g., budget, 3-star) |

#### Pricing & Commercial Flags

| Field | Meaning |
|---|---|
| `Original Price` | Base price before discount |
| `Discounted Price` | Final price after discount |
| `Discount Percentage` | Percentage reduction applied |
| `Product Has Discount` | Boolean: discount currently active |
| `Is Best Seller` | Flagged as a bestselling tour |
| `Is Selling Fast` | Urgency flag for high-demand tours |
| `Is Budget Tour` | Positioned as a budget option |
| `Is Luxury Tour` | Positioned as a luxury option |
| `Is Tour Customizable` | Can be customized on request |

#### Ratings & Operator

| Field | Meaning |
|---|---|
| `Rating Score` | Average review score |
| `Rating Count` | Number of reviews |
| `Physical Rating Level` | Difficulty/fitness level required |
| `Tour Operator ID` | Unique ID of the operating company |
| `Tour Operator` | Operator name and details |
| `Default Version ID` | Default tour version/package ID |
| `Available Regions` | Regions where the tour can be booked |

***

### How to Use

1. **Get search URLs** — Run a search on Bookmundi (e.g., destination, duration, type) and copy the results page URL. Append `?page=N` for additional pages.
2. **Configure input** — Paste URLs into `urls`. Set `max_items_per_url` based on how many results per page you expect (typically up to 20–30 per page; set higher to be safe).
3. **Run the scraper** — Start the actor. Enable `ignore_url_failures: true` for multi-URL runs.
4. **Export** — Download as JSON, CSV, or Excel.

**Tips:**

- Filter URLs by tour type, price, or duration to collect targeted subsets.
- Combine multiple destination URLs in one run for regional comparisons.
- If a URL returns 0 results, confirm it loads correctly in a browser — Bookmundi may require specific query parameters.

***

### Use Cases & Business Value

- **Price intelligence:** Track how operators adjust pricing and discounts over time
- **Inventory feeds:** Populate or update a tour aggregator database
- **Destination analysis:** Compare tour supply, types, and ratings across destinations
- **Operator research:** Profile tour operators by volume, ratings, and pricing tier

***

### Conclusion

The **Bookmundi Tours Search Scraper** delivers structured, detailed tour data directly from search results — no manual copying, no pagination headaches. With 50+ fields covering pricing, geography, tour types, and operator metadata, it gives travel businesses and researchers the data foundation they need to move fast.

# Actor input Schema

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

Add the URLs of the Tours list urls you want to scrape. You can paste URLs one by one, or use the Bulk edit section to add a prepared list.

## `ignore_url_failures` (type: `boolean`):

If true, the scraper will continue running even if some URLs fail to be scraped.

## `keyword` (type: `string`):

Enter the keyword to search for items

## `sort_by` (type: `string`):

Sort items by options

## `duration` (type: `string`):

Enter the duration to search for items

## `price_range` (type: `string`):

Enter the Price Range to search for items

## `is_group_tour` (type: `boolean`):

Enter the is_group_tour to search for items

## `is_small_group_tour` (type: `boolean`):

Enter the is_small_group_tour to search for items

## `has_discount` (type: `boolean`):

Enter the has_discount to search for items

## `country` (type: `string`):

Enter the country to search for items

## `activity` (type: `string`):

Enter the activity to search for items

## `page` (type: `integer`):

Specify the page number to start scraping from

## `max_items_per_url` (type: `integer`):

The maximum number of items to scrape per URL.

## Actor input object example

```json
{
  "urls": [
    "https://www.bookmundi.com/s/italy?page=10"
  ],
  "ignore_url_failures": true,
  "max_items_per_url": 20
}
```

# 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 = {
    "urls": [
        "https://www.bookmundi.com/s/italy?page=10"
    ],
    "ignore_url_failures": true,
    "is_group_tour": false,
    "is_small_group_tour": false,
    "has_discount": false,
    "max_items_per_url": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("stealth_mode/bookmundi-tours-search-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 = {
    "urls": ["https://www.bookmundi.com/s/italy?page=10"],
    "ignore_url_failures": True,
    "is_group_tour": False,
    "is_small_group_tour": False,
    "has_discount": False,
    "max_items_per_url": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("stealth_mode/bookmundi-tours-search-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 '{
  "urls": [
    "https://www.bookmundi.com/s/italy?page=10"
  ],
  "ignore_url_failures": true,
  "is_group_tour": false,
  "is_small_group_tour": false,
  "has_discount": false,
  "max_items_per_url": 20
}' |
apify call stealth_mode/bookmundi-tours-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stealth_mode/bookmundi-tours-search-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/fdqIrECmMdtahfYiM/builds/lQUqvIi97ZZTUX9hj/openapi.json
