# Renfe Scraper - Spanish Train Tickets & Prices (`studio-amba/renfe-scraper`) Actor

Scrape train schedules, prices, and availability from Renfe (renfe.com), Spain's national railway. Search AVE high-speed, Alvia, Media Distancia, and Cercanias routes. No login or cookies needed.

- **URL**: https://apify.com/studio-amba/renfe-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result scrapeds

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

## Renfe Scraper

Scrape **train schedules, prices, and availability** from [Renfe](https://www.renfe.com), Spain's national railway operator. Extract data for AVE high-speed, Alvia, AVLO low-cost, Media Distancia, and regional train services. No login or cookies required.

### How to scrape Renfe data

Renfe is Spain's national railway company, operating over 5,000 trains daily across the country. This scraper extracts structured train connection data including departure/arrival times, prices, train types, and seat classes directly from the Renfe website.

Use this actor to:

- **Monitor train prices** across routes and dates
- **Compare fare classes** (Turista, Turista Plus, Preferente)
- **Track AVE high-speed availability** between major Spanish cities
- **Build travel datasets** for research, analytics, or price comparison tools
- **Automate price alerts** by scheduling regular runs

### Why use this actor?

- **No login, no cookies, no API key needed** — works out of the box
- **All train types covered** — AVE, AVLO, Alvia, Altaria, Euromed, Media Distancia, Regional, Cercanias
- **Structured JSON output** — clean, machine-readable data ready for analysis
- **Runs on Apify platform** — scheduling, API access, webhooks, and integrations included
- **Proxy rotation** — residential proxies for reliable access without blocking

### Input

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `origin` | String | No | `Madrid` | Departure city or station name |
| `destination` | String | No | `Barcelona` | Arrival city or station name |
| `departureDate` | String | No | Tomorrow+2 | Travel date in YYYY-MM-DD format |
| `maxResults` | Integer | No | `50` | Maximum number of connections to return |
| `proxyConfiguration` | Object | No | Residential ES | Proxy settings for reliability |

#### Example input

```json
{
    "origin": "Madrid",
    "destination": "Barcelona",
    "departureDate": "2026-07-15",
    "maxResults": 30,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "ES"
    }
}
```

#### Popular routes to try

- Madrid to Barcelona (AVE high-speed, ~2.5h)
- Madrid to Sevilla (AVE, ~2.5h)
- Madrid to Valencia (AVE, ~1.5h)
- Barcelona to Valencia (Euromed/AVE, ~3h)
- Madrid to Malaga (AVE, ~2.5h)
- Madrid to Zaragoza (AVE, ~1.25h)

### Output

Each result contains:

| Field | Type | Example |
|-------|------|---------|
| `origin` | String | `"Madrid"` |
| `destination` | String | `"Barcelona"` |
| `departureTime` | String | `"08:00"` |
| `arrivalTime` | String | `"10:30"` |
| `duration` | String | `"2h 30min"` |
| `trainType` | String | `"AVE"` |
| `trainNumber` | String | `"03091"` |
| `price` | Number | `35.50` |
| `currency` | String | `"EUR"` |
| `seatClass` | String | `"Turista"` |
| `carrier` | String | `"Renfe"` |
| `url` | String | Link to search results |
| `scrapedAt` | String | ISO 8601 timestamp |

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel from the Output tab.

### Example output

```json
{
    "origin": "Madrid",
    "destination": "Barcelona",
    "departureTime": "08:00",
    "arrivalTime": "10:30",
    "duration": "2h 30min",
    "trainType": "AVE",
    "trainNumber": "03091",
    "price": 35.50,
    "currency": "EUR",
    "seatClass": "Turista",
    "carrier": "Renfe",
    "url": "https://www.renfe.com/es/en",
    "scrapedAt": "2026-06-09T14:30:00.000Z"
}
```

### How much does it cost to scrape Renfe?

This actor is a lightweight HTTP scraper (no browser), so it runs fast and cheap. It costs $0.02 per run plus $0.002 per result, regardless of proxy type.

| Use case | Estimated cost |
|----------|----------------|
| Single route search (50 trains) | ~$0.12 |
| Daily monitoring of 10 routes (50 trains each) | ~$1.20/day |
| Weekly price comparison (50 routes) | ~$0.50-1.00/week |

Costs may vary based on proxy usage and actor execution time.

### Tips

- **Use Spanish proxy** — Set `apifyProxyCountry` to `ES` for best results. Renfe may show different availability to non-Spanish IPs.
- **Book dates in advance** — Renfe releases tickets 60-90 days ahead. Searching too far in the future may return no results.
- **Schedule runs** — Set up daily or weekly runs to track price changes over time.
- **Empty results?** — Check the debug screenshot saved in the key-value store. Renfe's website changes frequently.
- **AVLO low-cost** — Renfe's low-cost AVE service (AVLO) has limited availability and may not show on all routes.

### Renfe train types

| Type | Service | Speed |
|------|---------|-------|
| AVE | High-speed long distance | Up to 310 km/h |
| AVLO | Low-cost high-speed | Up to 310 km/h |
| Alvia | Long distance (variable gauge) | Up to 250 km/h |
| Euromed | Mediterranean corridor | Up to 220 km/h |
| Altaria | Long distance diesel | Up to 200 km/h |
| Media Distancia | Medium distance regional | Up to 160 km/h |
| Regional | Short distance | Up to 120 km/h |
| Cercanias | Suburban commuter | Up to 100 km/h |

### Limitations

- Renfe's website uses heavy JavaScript rendering and may change its structure without notice
- Prices shown are indicative and may differ from final booking prices
- Some connections may not be available for online booking
- The scraper searches one route per run; use multiple runs for multiple routes
- Results depend on Renfe's website availability and may occasionally return fewer results

### FAQ

**Is scraping Renfe legal?**
This actor extracts publicly available information from Renfe's website. Always review and comply with Renfe's Terms of Service before use.

**Why are there no results?**
Renfe's website is heavily JavaScript-based and may block automated access. Try using residential proxies with a Spanish IP. Check the debug screenshot in the key-value store for more information.

**Can I search return trips?**
Currently the actor searches one-way connections. Run the actor twice with swapped origin/destination for return trips.

**How often should I run it?**
For price monitoring, daily runs are recommended. Renfe prices change frequently, especially for popular routes like Madrid-Barcelona.

### Support

Found a bug or need a custom solution? Open an issue in the [Issues tab](https://console.apify.com/actors/studio-amba~renfe-scraper/issues) or contact us directly.

# Actor input Schema

## `origin` (type: `string`):

Departure city or station name (e.g., 'Madrid', 'Barcelona', 'Sevilla'). The scraper will auto-select the main station.

## `destination` (type: `string`):

Arrival city or station name (e.g., 'Barcelona', 'Valencia', 'Malaga'). The scraper will auto-select the main station.

## `departureDate` (type: `string`):

Travel date in YYYY-MM-DD format. Defaults to tomorrow if not provided.

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

Maximum number of train connections to return.

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

Proxy settings. Residential proxies recommended for Renfe.

## Actor input object example

```json
{
  "origin": "Madrid",
  "destination": "Barcelona",
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "ES"
  }
}
```

# Actor output Schema

## `results` (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 = {
    "origin": "Madrid",
    "destination": "Barcelona",
    "departureDate": "",
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "ES"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/renfe-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 = {
    "origin": "Madrid",
    "destination": "Barcelona",
    "departureDate": "",
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "ES",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/renfe-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 '{
  "origin": "Madrid",
  "destination": "Barcelona",
  "departureDate": "",
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "ES"
  }
}' |
apify call studio-amba/renfe-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/renfe-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/G9xWesnHjmFTQgZTU/builds/VHCLGCQINKlXCgfwc/openapi.json
