# Aviasales hot tickets scraper (`volarai/aviasales-hot-tickets-scraper`)

Scrapes hot tickets prices from Aviasales.
Extracts destination, price, discount, and dates. Uses Selenium. Saves data to Apify dataset.
Hot ticket page example for Moscow: https://www.aviasales.ru/?params=MOW1\&service=hottickets\&marker=70279

- **URL**: https://apify.com/volarai/aviasales-hot-tickets-scraper.md
- **Developed by:** [VolarAI](https://apify.com/volarai) (community)
- **Categories:** Travel, Automation, News
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

# README

### English

#### Project Summary

This project is an Apify actor that scrapes hot ticket offers from Aviasales using Selenium and Chrome WebDriver. It extracts discounted flight ticket information from the Aviasales site, processes the data, and stores the results in the Apify dataset.

#### How to Use

1. **Install dependencies:**
   - Python 3.8+ required
   - Install required packages:
     ```bash
     pip install selenium apify-client
     ```
   - Ensure Chrome browser is installed and compatible [ChromeDriver](https://chromedriver.chromium.org/) is available.

2. **Configure input:**
   - The actor expects an input JSON file with the following fields:
     - `departure_city` (string): IATA code for the departure city (e.g., "KZN", "LED")
     - `language` (string): Language/market code ("ru", etc.)

3. **Run the script locally:**
   ```bash
   python src/main.py
   ```
   Or deploy on [Apify platform](https://apify.com/).

#### What the Script Does

- Initializes as an Apify Actor and gets input (departure city, language)
- Builds the Aviasales URL for hot tickets with the specified parameters
- Launches a Selenium Chrome WebDriver (headless mode supported)
- Enqueues the target URL for processing
- Scrapes hot ticket offers, extracting for each ticket:
  - Destination city (city of arrival)
  - Comments (if present)
  - Price and old (original) price
  - Flight date, start & end time, duration
  - Calculates discount percentage
- Pushes the structured data to an Apify dataset

#### Expected Input Example

```json
{
  "departure_city": "KZN",
  "language": "ru"
}
```

**Note:** Currently, the extraction and output of offers works only for the Russian language.

#### Output

Each extracted ticket will be stored as a record with fields:

- `City`: destination city (город назначения)
- `Comment`: special notes (if available)
- `price`: current price
- `old_price`: original price
- `discount`: discount percentage
- `date`, `time_start`, `time_end`, `duration`: timing info

Results are saved to the default Apify dataset and printed to the console during execution.

***

### Русский

#### Описание проекта

Этот проект — Apify-актор, который с помощью Selenium и Chrome WebDriver парсит горячие предложения авиабилетов с сайта Aviasales. Скрипт собирает данные о скидках на билеты, обрабатывает их и сохраняет в датасет Apify.

#### Как использовать

1. **Установите зависимости:**
   - Требуется Python 3.8+
   - Установите библиотеки:
     ```bash
     pip install selenium apify-client
     ```
   - Убедитесь, что у вас установлен браузер Chrome и подходящий [ChromeDriver](https://chromedriver.chromium.org/).

2. **Настройте входные параметры:**
   - Скрипт ожидает JSON-файл с такими полями:
     - `departure_city` (строка): IATA-код города отправления (например, "KZN", "LED")
     - `language` (строка): код языка/рынка ("ru" и др.)

3. **Запуск скрипта локально:**
   ```bash
   python src/main.py
   ```
   Или разверните на платформе [Apify](https://apify.com/).

#### Описание работы скрипта

- Инициализация актора Apify и получение входных параметров
- Формирование целевого URL для горячих билетов Aviasales
- Запуск Selenium Chrome WebDriver (поддерживается headless режим)
- Добавление URL в очередь обработки
- Сбор данных о билетах:
  - Город назначения
  - Комментарии (если есть)
  - Цена и старая (оригинальная) цена
  - Дата, время вылета и прилёта, длительность
  - Расчёт процента скидки
- Сохранение структурированных данных в датасет Apify

#### Пример входных данных

```json
{
  "departure_city": "KZN",
  "language": "ru"
}
```

**Примечание:** В настоящее время вывод предложений работает только на русском языке.

#### Выходные данные

Каждая запись содержит:

- `City`: город назначения
- `Comment`: примечания (если есть)
- `price`: текущая цена
- `old_price`: оригинальная цена
- `discount`: процент скидки
- `date`, `time_start`, `time_end`, `duration`: информация о времени

Результаты сохраняются в датасет Apify и выводятся в консоль.

***

# Actor input Schema

## `departure_city` (type: `string`):

Departure city for hot air tickets in IATA format. Example: MOW if Moscow

## `language` (type: `string`):

Language for text hot tickets

## Actor input object example

```json
{
  "departure_city": "MOW",
  "language": "ru"
}
```

# Actor output Schema

## `tickets` (type: `string`):

List of hot tickets scraped from Aviasales

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("volarai/aviasales-hot-tickets-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("volarai/aviasales-hot-tickets-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call volarai/aviasales-hot-tickets-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=volarai/aviasales-hot-tickets-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Aviasales hot tickets scraper",
        "description": "Scrapes hot tickets prices from Aviasales. \nExtracts destination, price, discount, and dates. Uses Selenium. Saves data to Apify dataset.\nHot ticket page example for Moscow: https://www.aviasales.ru/?params=MOW1&service=hottickets&marker=70279",
        "version": "0.1",
        "x-build-id": "zh3c9AJ9mDOFK4Gbn"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/volarai~aviasales-hot-tickets-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-volarai-aviasales-hot-tickets-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/volarai~aviasales-hot-tickets-scraper/runs": {
            "post": {
                "operationId": "runs-sync-volarai-aviasales-hot-tickets-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/volarai~aviasales-hot-tickets-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-volarai-aviasales-hot-tickets-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": [
                    "departure_city"
                ],
                "properties": {
                    "departure_city": {
                        "title": "Departure city (IATA format)",
                        "type": "string",
                        "description": "Departure city for hot air tickets in IATA format. Example: MOW if Moscow",
                        "default": "MOW"
                    },
                    "language": {
                        "title": "Language",
                        "type": "string",
                        "description": "Language for text hot tickets",
                        "default": "ru"
                    }
                }
            },
            "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
                                    }
                                }
                            },
                            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
