# Transitland Scraper — Transit Routes & Departures (`ponderable_hydrometer/transitland-scraper`) Actor

Public-transport data from Transitland — operators, routes, stops and scheduled + real-time departures across thousands of cities worldwide. Bring your own free key.

- **URL**: https://apify.com/ponderable\_hydrometer/transitland-scraper.md
- **Developed by:** [Ponderable Hydrometer](https://apify.com/ponderable_hydrometer) (community)
- **Categories:** Developer tools, Automation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.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.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## Transitland Scraper — Transit Data Worldwide

**One actor for public transit across the whole planet — operators (agencies), routes, stops and
real-time + scheduled departures for thousands of cities** (Bucharest, Vienna, Barcelona, Budapest,
London and many more), all from [Transitland](https://www.transit.land)'s GTFS/GTFS-RT aggregator,
in one normalized schema.

Perfect for trip planners, live departure boards, transit dashboards, coverage analysis and datasets.

### Bring your own key (free)

Transitland requires a **free** API key. Get one at
<https://www.transit.land/documentation#signing-up-for-an-api-key> and set it in the `apiKey`
input (stored as a secret). If the key is missing or invalid the actor logs a clear message and
**exits cleanly with no results** (Transitland returns `401` without a key) — it never burns a run
guessing.

### Modes

| Mode | What it returns |
|------|-----------------|
| `operators` | Agencies matching a search — name, OnestopID, nested agencies, city/region/country |
| `routes` | Routes of an operator (or by search) — short/long name, type, color, agency |
| `stops` | Stops by radius (`lat`+`lon`+`radius`), by `servedByOnestopIds`, or search |
| `departures` | Real-time + scheduled departures at a stop — route, headsign, times, delay |

### What you get

- **Operators** — `onestopId`, `name`, `website`, `agencyCount`, nested `agencies` with places,
  and top-level `city`/`region`/`country`
- **Routes** — `onestopId`, `routeId`, short/long name, `routeType` + human `routeTypeName`
  (tram/metro/rail/bus/ferry/…), `color`, `textColor`, agency
- **Stops** — `onestopId`, `stopName`, `stopCode`, `lat`/`lon`, `servedByRouteTypes`,
  `servedByOnestopIds`, wheelchair boarding, place
- **Departures** — scheduled vs. estimated departure/arrival, `departureDelay`, `stopHeadsign`,
  trip & route info, `scheduleRelationship`

### Example inputs

**Find an operator**

```json
{"mode":"operators","search":"Wiener Linien","apiKey":"<your-key>"}
```

**Routes of an operator**

```json
{"mode":"routes","operatorId":"o-u281-...","apiKey":"<your-key>","maxResults":300}
```

**Stops near a point**

```json
{"mode":"stops","lat":"44.4268","lon":"26.1025","radius":500,"apiKey":"<your-key>"}
```

**Live departures at a stop**

```json
{"mode":"departures","stopId":"s-...","apiKey":"<your-key>","maxResults":50}
```

Typical flow: `operators` → grab an `onestopId` → `routes`/`stops` → grab a stop `onestopId` → `departures`.

### Output (one departure)

Fields below are the real normalizer output:

```json
{
  "stopOnestopId": "s-u281z7-example",
  "stopName": "Karlsplatz",
  "serviceDate": "2026-07-12",
  "scheduledDeparture": "10:15:00",
  "estimatedDeparture": "10:16:20",
  "departureDelay": 80,
  "scheduledArrival": "10:15:00",
  "estimatedArrival": "10:16:20",
  "arrivalDelay": 80,
  "scheduleRelationship": "SCHEDULED",
  "stopHeadsign": "Reumannplatz",
  "stopSequence": 4,
  "tripId": "trip-123",
  "tripHeadsign": "Reumannplatz",
  "directionId": 0,
  "routeShortName": "U1",
  "routeLongName": "Leopoldau - Oberlaa",
  "routeType": 1,
  "routeTypeName": "metro",
  "routeOnestopId": "r-u281-u1"
}
```

### Why this actor

- **Whole planet, one listing** — Transitland aggregates thousands of GTFS feeds into one schema.
- **Departures are the wedge** — real-time (estimated + delay) *and* scheduled times per stop, which
  few competitors expose cleanly.
- **Reliable** — cursor paging via `meta.next` and 429/5xx backoff.

### Pricing

Pay per result — **$3.00 per 1,000 results** (one result = one operator / route / stop / departure).
No subscription or platform fees. You supply your own free transit.land key.

### Related actors

- **TfL London Scraper** — London Tube/bus/DLR live arrivals & line status.
- **Vienna Wiener Linien** — live Vienna departures & stops.

### Notes & limits

- Real-time departures reflect the feed's freshness; treat each run as a snapshot.
- Independent tool built on the Transitland REST API; not affiliated with or endorsed by Transitland
  / Interline. You are responsible for compliant use of the output.

# Actor input Schema

## `mode` (type: `string`):

What to fetch: operators (agencies), routes, stops, or departures (real-time + scheduled) from a stop.

## `search` (type: `string`):

Full-text search. For operators: agency/city name (e.g. "Bucharest", "Wiener Linien", "Barcelona"). For routes/stops: name search.

## `operatorId` (type: `string`):

For mode=routes: list all routes of one operator, e.g. "o-u281-..." (get it from an operators run).

## `stopId` (type: `string`):

For mode=departures: the stop to fetch departures for, e.g. "s-u281-..." (get it from a stops run).

## `servedByOnestopIds` (type: `array`):

For mode=stops/routes: filter to entities served by these route/operator OnestopIDs.

## `lat` (type: `string`):

For mode=stops: center latitude for a radius search (needs lat + lon + radius).

## `lon` (type: `string`):

For mode=stops: center longitude for a radius search.

## `radius` (type: `integer`):

For mode=stops: search radius in meters around lat/lon (max 10000).

## `apiKey` (type: `string`):

Your free transit.land API key. Get one at https://www.transit.land/documentation#signing-up-for-an-api-key . Required — Transitland does not work keyless.

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

Cap on number of rows returned.

## Actor input object example

```json
{
  "mode": "operators",
  "search": "Bucharest",
  "maxResults": 200
}
```

# 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 = {
    "search": "Bucharest"
};

// Run the Actor and wait for it to finish
const run = await client.actor("ponderable_hydrometer/transitland-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 = { "search": "Bucharest" }

# Run the Actor and wait for it to finish
run = client.actor("ponderable_hydrometer/transitland-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 '{
  "search": "Bucharest"
}' |
apify call ponderable_hydrometer/transitland-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ponderable_hydrometer/transitland-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/bbD7xTgYiPCs6frf0/builds/7KA5akLMSWydELkcd/openapi.json
