# GB NaPTAN Transit Node Records — DfT Stops (`nexgensignal/gb-naptan-transit-node-records`) Actor

Keyless, pay-per-record DfT NaPTAN data. One row per access node — ATCO/NaPTAN code, name, locality, town, coordinates, stop type, plus status and modification metadata verbatim. Stop/infrastructure grain; OGL v3.0; no person data.

- **URL**: https://apify.com/nexgensignal/gb-naptan-transit-node-records.md
- **Developed by:** [NexGen Signal](https://apify.com/nexgensignal) (community)
- **Categories:** Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $33.50 / 1,000 access node records

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

## GB NaPTAN Transit Node Records — DfT Stops

**Keyless. Pay per record. Every public-transport stop and access node in Great Britain, as one clean table.**

This actor turns the **UK Department for Transport** NaPTAN (National Public Transport Access Nodes) dataset into clean, per-node records — the official register of every bus stop, rail station, metro entrance, ferry berth, and other public-transport access node in Great Britain. Each run reads the DfT's keyless NaPTAN CSV and delivers one row per access node: its ATCO and NaPTAN codes, the stop name and locality, the street and landmark, the coordinates, the stop type, and — carried **verbatim** — its status and modification metadata. Stop / access-node infrastructure grain, structured for engineering use, under the Open Government Licence, with no personal data of any kind.

### What this is, in one paragraph

NaPTAN is the national database of public-transport access nodes — the canonical identifiers that journey planners, timetables, and ticketing systems use to refer to a stop. This actor reads that dataset and flattens each node into a single analysis-ready record: the ATCO code (the national identifier) and NaPTAN code, the common name and short name, the landmark, street, crossing, and indicator, the locality hierarchy and town, the OSGR easting/northing and WGS84 longitude/latitude, the stop type and bus-stop type, the timing status, and the administrative area — plus the node's creation and modification datetimes, revision number, modification flag, and status. It is the infrastructure map that transport systems are built on. Values are exactly as published. You are billed only for records actually delivered.

### Who buys this and for what job

- **Journey-planning, mobility, and MaaS products** that need the canonical stop register with stable identifiers.
- **Transport-analytics and planning teams** mapping stop coverage by locality, town, and stop type.
- **Logistics, micro-mobility, and location products** joining to the national access-node identifiers.
- **Data engineers** who want the NaPTAN register as clean rows without downloading and reshaping a ~102MB CSV by hand.

### Open Government Licence — free commercial reuse

One licence rider travels on every record. NaPTAN data is published under the **Open Government Licence v3.0 (OGL v3.0)** — free to copy, publish, distribute, and adapt, **including commercially**, with the required attribution: "Contains public sector information licensed under the Open Government Licence v3.0." One honest caveat rides too: this is the stop register, not a live departures or service feed — for real-time services, use a departures API keyed on the ATCO code.

### Infrastructure grain — no person data

The unit of every record is an access node — infrastructure, never a person. The common name, street, landmark, locality, and town are place descriptors, not people; the register carries no natural-person fields, and this actor emits none, with a person-key guard as a pure backstop.

### Status and modification metadata — verbatim

The dispatch's rider is honored: each node's `status`, `modification`, `modification_date_time`, `creation_date_time`, and `revision_number` are carried **verbatim**. That lets a downstream consumer distinguish active from inactive nodes and diff two pulls to see which nodes were created, modified, or retired between versions — the change signal that keeps a stop table current.

### Pricing

| Event | Free plan | Bronze | Silver | Gold / Platinum / Diamond |
|-------|-----------|--------|--------|---------------------------|
| `access_node_record` | $0.05 | $0.045 | $0.04 | $0.0335 |

Delivered before charged. Blocked runs and empty results cost nothing.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `stopType` | string | — | Optional. Keep only nodes of this StopType code (e.g. BCT bus stop, RLY rail station, MET metro). |
| `localityContains` | string | — | Optional. Keep only nodes whose locality name contains this text. |
| `townContains` | string | — | Optional. Keep only nodes whose town contains this text. |
| `status` | string | — | Optional. Keep only nodes with this status (e.g. active, inactive). |
| `maxRecords` | integer | 500 | Ceiling on records delivered and billed. Bounds this ~435,000-node dataset. |

### Output

One JSON object per access node. Real example (values as published):

```json
{
  "record_id": "0100BRP90317",
  "atco_code": "0100BRP90317",
  "naptan_code": "bstjada",
  "common_name": "Temple Meads Stn",
  "street": "Temple Gate",
  "indicator": "T1",
  "bearing": "SE",
  "locality_name": "Bristol City Centre",
  "town": "Bristol",
  "longitude": -2.58,
  "latitude": 51.44,
  "stop_type": "BCT",
  "bus_stop_type": "MKD",
  "status": "active",
  "modification_date_time": "2020-01-01T00:00:00",
  "revision_number": "3",
  "source": "UK DfT NaPTAN",
  "licence": "UK Department for Transport NaPTAN ... Open Government Licence v3.0 ...",
  "disclaimer": "Public-transport access-node (stop) infrastructure records ... status and modification metadata are carried VERBATIM ...",
  "observed_at": "2026-08-22T00:00:00Z"
}
```

An unbilled `RUN_RECEIPT` records the robots check, the filters, rows seen and delivered, and whether charged equals delivered.

### Field reference

Each record is one access node. Identity: `record_id` / `atco_code`, `naptan_code`, `common_name`, and `short_common_name`. Placement: `landmark`, `street`, `crossing`, `indicator`, and `bearing`. Locality: `nptg_locality_code`, `locality_name`, `parent_locality_name`, `town`, and `suburb`. Geography: `easting`, `northing`, `longitude`, and `latitude`. Type: `stop_type`, `bus_stop_type`, `timing_status`, and `administrative_area_code`. Status and change (verbatim): `creation_date_time`, `modification_date_time`, `revision_number`, `modification`, and `status`. Provenance: `source`, `source_url`, `licence`, `attribution`, `disclaimer`, and `observed_at`.

### How a run works

A run first re-reads the source host's robots posture from your runtime — the NaPTAN API host — and stops at the door if a Disallow ever covers the access-nodes path. It then streams the NaPTAN CSV (around 102MB) without buffering the whole file, applies your optional `stopType`, `localityContains`, `townContains`, and `status` filters, and flattens each node to one record — carrying the status and modification metadata **verbatim**, never anything person-shaped — delivered **before** it is charged, so a blocked or empty run costs you nothing. The actor stops at your `maxRecords` ceiling and records `charge_equals_delivered` in the receipt.

### Coverage and scope

The register holds on the order of **435,000+ access nodes** across Great Britain — bus stops, rail and metro stations, ferry and tram nodes, and more. Because each record carries the `stop_type`, `locality_name`, and `town`, segmenting by node type or place is a single filter, and the coordinates place every node on a map. Pull one town or one stop type for a focused inventory, or bound a larger pull with `maxRecords`; a whole-country pull is a large, one-time seed.

### Cost guidance

One `access_node_record` per delivered node: cost = nodes delivered × your plan's per-record price. Scope with `stopType`, `localityContains`, `townContains`, or `status`, and cap with `maxRecords`. 1,000 nodes is **$50** (Free) / **$33.50** (Gold). The whole ~435,000-node register is possible but large; scope first.

### Honest limitations

- **A register, not a live feed.** These are access-node records, not real-time departures or services; join to a departures API on the ATCO code for live data.
- **Large dataset.** Bound pulls with filters and `maxRecords`; a whole-country pull is a large one-time seed.
- **As published.** Node attributes, status, and modification metadata are exactly as the DfT distributes them, carried verbatim.
- **No person data** of any kind.

### Differentiation

This is a **net-new** category for the NexGenData fleet — no existing fleet actor covers the GB public-transport stop register. It is distinct from any road, flood, or vehicle cell: this is the **NaPTAN access-node infrastructure register**, the canonical stop identifiers that journey-planning and mobility systems join against.

### The NexGen Signal family

Part of the NexGen Signal family of pay-per-record data products:

- [UK Road Collision Records — DfT STATS19](https://apify.com/nexgensignal/uk-road-collision-records)
- [England Flood Station Records — EA Monitoring](https://apify.com/nexgensignal/england-flood-station-records)
- [UK Company Status Records — Companies House](https://apify.com/nexgensignal/uk-company-status-records)
- [UK Tariff Commodity Records — HS Codes & Taxonomy](https://apify.com/nexgensignal/uk-tariff-commodity-records)
- [Airport Facility Records — US FAA NASR](https://apify.com/nexgensignal/airport-facility-records)

*Source: UK Department for Transport, NaPTAN (naptan.api.dft.gov.uk). Contains public sector information licensed under the Open Government Licence v3.0 — free to reuse, including commercially, with attribution. Stop / access-node infrastructure grain; status and modification metadata carried verbatim. A stop register, not a live departures feed; no person data of any kind.*

# Actor input Schema

## `stopType` (type: `string`):

Optional. Keep only nodes of this StopType code (e.g. BCT bus stop, RLY rail station, MET metro).

## `localityContains` (type: `string`):

Optional. Keep only nodes whose locality name contains this text.

## `townContains` (type: `string`):

Optional. Keep only nodes whose town contains this text.

## `status` (type: `string`):

Optional. Keep only nodes with this status (e.g. active, inactive).

## `maxRecords` (type: `integer`):

Maximum records delivered and billed. Bounds this ~435,000-node dataset.

## Actor input object example

```json
{
  "maxRecords": 500
}
```

# Actor output Schema

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

Delivered 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 = {
    "maxRecords": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexgensignal/gb-naptan-transit-node-records").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 = { "maxRecords": 500 }

# Run the Actor and wait for it to finish
run = client.actor("nexgensignal/gb-naptan-transit-node-records").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 '{
  "maxRecords": 500
}' |
apify call nexgensignal/gb-naptan-transit-node-records --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nexgensignal/gb-naptan-transit-node-records"
        }
    }
}
```

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/H9QM5ASTBXCECfWP7/builds/diMY0tub0KDdPeYf6/openapi.json
