# National Rail Train Ticket & Connection Scraper (`muhammadafzal/national-rail-train-ticket-connection-scraper`) Actor

Scrape UK National Rail connections, schedules, operators, live status, journey legs, ticket types, and GBP fares.

- **URL**: https://apify.com/muhammadafzal/national-rail-train-ticket-connection-scraper.md
- **Developed by:** [Muhammad Afzal](https://apify.com/muhammadafzal) (community)
- **Categories:** Travel, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 train connections

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## National Rail Train Ticket & Connection Scraper

Find live UK train connections, timetable information, operators, train legs, service status, and ticket fares from National Rail's public Journey Planner. Use it for route comparison, travel-planning assistants, fare research, timetable monitoring, and downstream itinerary selection.

The Actor uses National Rail's page-owned journey-planning service. It does not log in, buy tickets, bypass a CAPTCHA, or promise a ticket reservation. Fares and realtime status are point-in-time results and can change before purchase.

### What it returns

Each default-dataset record is one outbound or return connection:

| Field | Description |
| --- | --- |
| `origin`, `destination` | Station names and 3-letter CRS codes |
| `departureScheduled`, `arrivalScheduled` | ISO-8601 times with UK offset |
| `departureRealtime`, `arrivalRealtime`, `status`, `delayMinutes` | Realtime status when supplied |
| `durationMinutes`, `changes`, `direct`, `isOvertaken` | Route comparison fields |
| `operators` | Train operator code and name |
| `cheapestFare`, `fares` | Ticket type, fare class, category, restriction, and GBP amount |
| `legs` | Train number/UID, board/alight stations, platforms, status, and replacement-bus flags |

The `OUTPUT` key-value record reports `DATA`, `EMPTY`, `PARTIAL`, `BLOCKED`, or `REJECTED`, plus delivery, scan, warning, and billing counts. It is deliberately separate from the homogeneous connection dataset so agents can distinguish a valid no-match from an access problem.

### Input

`from` and `to` accept a full station name or CRS code, such as `London Euston` or `EUS`. `departureDate` uses `YYYY-MM-DD`; if omitted, the Actor uses tomorrow in Europe/London. `departureTime` uses local UK `HH:mm` and defaults to `09:00`. `searchBy` can be `departure` or `arrival`.

Optional `returnDate` and `returnTime` add reverse-direction return connections. `adults` and `children` control the fare request. `fareClass` is `any`, `standard`, or `first`. Set `directOnly` to exclude journeys requiring a change, and set `includeOvertaken` to `false` to hide slower trains overtaken by a later departure. `maxResults` is capped at 20 across both directions.

Example input:

```json
{
  "from": "London Euston",
  "to": "Manchester Piccadilly",
  "departureDate": "2026-09-18",
  "departureTime": "09:00",
  "searchBy": "departure",
  "adults": 1,
  "children": 0,
  "fareClass": "any",
  "directOnly": false,
  "maxResults": 5
}
```

The API equivalent is a normal Apify Actor run:

```bash
apify call YOUR_USERNAME/national-rail-train-ticket-connection-scraper \
  -p '{"from":"London Euston","to":"Manchester Piccadilly","departureDate":"2026-09-18","departureTime":"09:00","maxResults":5}'
```

### Output example

```json
{
  "connectionId": "outbound-1-2026-09-18T09:13:00+01:00",
  "direction": "outbound",
  "origin": { "crsCode": "EUS", "name": "London Euston" },
  "destination": { "crsCode": "MAN", "name": "Manchester Piccadilly" },
  "departureScheduled": "2026-09-18T09:13:00+01:00",
  "arrivalScheduled": "2026-09-18T11:19:00+01:00",
  "durationMinutes": 126,
  "changes": 0,
  "direct": true,
  "status": "OnTime",
  "cheapestFare": { "ticketCode": "SVS", "ticketName": "Off-Peak Single", "amountGbp": 79.8, "fareClass": "STANDARD" }
}
```

### Pricing

This private development Actor is configured for Pay per event:

| Event | Price | Meaning |
| --- | ---: | --- |
| Actor start | $0.00005 | One bounded search start; synthetic platform event |
| Train connection | $0.002 | One schema-valid connection delivered to the default dataset |

A one-result run therefore has a $0.002 result charge plus the synthetic start event. Runs stop when the user's maximum charge is reached. Invalid input and station-resolution failures do not create result events.

### Reliability and limits

The scraper resolves stations from National Rail's public station list, uses a single bounded search request per direction, retries 429 and 5xx responses with capped backoff, and limits each run to 20 records. It preserves valid partial records and writes warnings to `OUTPUT`. A truthful no-match query returns an empty dataset with an `EMPTY` summary; HTTP denial, throttling, malformed source responses, and missing source data are reported as `BLOCKED` or `PARTIAL` rather than fabricated fares.

The public service can change schedules, prices, service status, station availability, or response fields. National Rail's official journey planner remains the source of truth for purchase eligibility. The Actor does not include Railcard discounts because users must supply and verify their own Railcard eligibility at checkout.

### Legal and responsible use

Use the Actor for permitted public-data research and itinerary planning. Respect National Rail terms, rate limits, and applicable law. Do not use the dataset to misrepresent live availability, scrape private account data, or automate ticket purchasing. The result is informational and is not a booking confirmation.

# Actor input Schema

## `from` (type: `string`):

Use this for the departure station. Enter a UK station name or 3-letter CRS code, for example `London Euston` or `EUS`.

## `to` (type: `string`):

Use this for the arrival station. Enter a UK station name or 3-letter CRS code, for example `Manchester Piccadilly` or `MAN`.

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

Use this to search a specific travel date in `YYYY-MM-DD` format. Omit it to use tomorrow in Europe/London time.

## `departureTime` (type: `string`):

Use this for the local UK time in `HH:mm` format. The default is `09:00`.

## `searchBy` (type: `string`):

Use `departure` to find trains leaving after the chosen time, or `arrival` to find trains arriving by it.

## `returnDate` (type: `string`):

Use this to add reverse-direction return connections in `YYYY-MM-DD` format. Omit for a single journey.

## `returnTime` (type: `string`):

Use this with Return date for the local UK return time in `HH:mm` format. Defaults to the departure time.

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

Use this for travellers aged 16 or older. Accepted range: 0-9; at least one total passenger is required.

## `children` (type: `integer`):

Use this for travellers aged 5-15. Accepted range: 0-9; children under 5 are not represented in fare quotes.

## `fareClass` (type: `string`):

Use this to keep any, Standard, or First Class fares in each connection.

## `directOnly` (type: `boolean`):

Use this to exclude connections that require changing trains. The default includes direct and connecting journeys.

## `includeOvertaken` (type: `boolean`):

Use this to include journeys where a later departure arrives sooner. Disable it for a tighter result set.

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

Use this to cap delivered records across outbound and return directions. Accepted range: 1-20; default 10.

## Actor input object example

```json
{
  "from": "London Euston",
  "to": "Manchester Piccadilly",
  "departureTime": "09:00",
  "searchBy": "departure",
  "adults": 1,
  "children": 0,
  "fareClass": "any",
  "directOnly": false,
  "includeOvertaken": true,
  "maxResults": 10
}
```

# Actor output Schema

## `output` (type: `string`):

JSON summary with outcome, counts, route, and warnings.

# 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 = {
    "from": "London Euston",
    "to": "Manchester Piccadilly",
    "departureTime": "09:00"
};

// Run the Actor and wait for it to finish
const run = await client.actor("muhammadafzal/national-rail-train-ticket-connection-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 = {
    "from": "London Euston",
    "to": "Manchester Piccadilly",
    "departureTime": "09:00",
}

# Run the Actor and wait for it to finish
run = client.actor("muhammadafzal/national-rail-train-ticket-connection-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 '{
  "from": "London Euston",
  "to": "Manchester Piccadilly",
  "departureTime": "09:00"
}' |
apify call muhammadafzal/national-rail-train-ticket-connection-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,muhammadafzal/national-rail-train-ticket-connection-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/Zr7VGAX8TEK0gXhE7/builds/Ngg6jbpEjXEv6PBZI/openapi.json
