Transport for London Unified API
tfl · Data
Our unified API brings together data across all modes of transport into a single RESTful API. This API provides access to the most highly requested realtime and status infomation across all the modes of transport, in a single and consistent way. Access to the developer documentation is available at https://api.tfl.gov.uk
Authentication
Sample Requests
Gets the places that lie within a geographic region. The geographic region of interest can either be specified by using a lat/lon geo-point and a radius in metres to return places within the locus defined by the lat/lon of its centre or alternatively, by the use of a boundi
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Place?type=json&radius=1&activeOnly=true&categories=example&placeGeo.lat=1&placeGeo.lon=1&placeGeo.neLat=1&placeGeo.neLon=1&placeGeo.swLat=1&placeGeo.swLon=1&includeChildren=true&numberOfPlacesToReturn=1"
import requests
params = {
"type": "json",
"radius": "1",
"activeOnly": "true",
"categories": "example",
"placeGeo.lat": "1",
"placeGeo.lon": "1",
"placeGeo.neLat": "1",
"placeGeo.neLon": "1",
"placeGeo.swLat": "1",
"placeGeo.swLon": "1",
"includeChildren": "true",
"numberOfPlacesToReturn": "1"
}
response = requests.get(
"https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Place",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Place');
url.searchParams.set('type', 'json');
url.searchParams.set('radius', '1');
url.searchParams.set('activeOnly', 'true');
url.searchParams.set('categories', 'example');
url.searchParams.set('placeGeo.lat', '1');
url.searchParams.set('placeGeo.lon', '1');
url.searchParams.set('placeGeo.neLat', '1');
url.searchParams.set('placeGeo.neLon', '1');
url.searchParams.set('placeGeo.swLat', '1');
url.searchParams.set('placeGeo.swLon', '1');
url.searchParams.set('includeChildren', 'true');
url.searchParams.set('numberOfPlacesToReturn', '1');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Place")
q := baseURL.Query()
q.Set("type", "json")
q.Set("radius", "1")
q.Set("activeOnly", "true")
q.Set("categories", "example")
q.Set("placeGeo.lat", "1")
q.Set("placeGeo.lon", "1")
q.Set("placeGeo.neLat", "1")
q.Set("placeGeo.neLon", "1")
q.Set("placeGeo.swLat", "1")
q.Set("placeGeo.swLon", "1")
q.Set("includeChildren", "true")
q.Set("numberOfPlacesToReturn", "1")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Place")
uri.query = URI.encode_www_form({
"type" => "json",
"radius" => "1",
"activeOnly" => "true",
"categories" => "example",
"placeGeo.lat" => "1",
"placeGeo.lon" => "1",
"placeGeo.neLat" => "1",
"placeGeo.neLon" => "1",
"placeGeo.swLat" => "1",
"placeGeo.swLon" => "1",
"includeChildren" => "true",
"numberOfPlacesToReturn" => "1"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Place?" . http_build_query([
"type" => "json",
"radius" => "1",
"activeOnly" => "true",
"categories" => "example",
"placeGeo.lat" => "1",
"placeGeo.lon" => "1",
"placeGeo.neLat" => "1",
"placeGeo.neLon" => "1",
"placeGeo.swLat" => "1",
"placeGeo.swLon" => "1",
"includeChildren" => "true",
"numberOfPlacesToReturn" => "1"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));Search the site for occurrences of the query string. The maximum number of results returned is equal to the maximum page size of 100. To return subsequent pages, use the paginated overload.
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Search?query=test"
import requests
params = {
"query": "test"
}
response = requests.get(
"https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Search",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Search');
url.searchParams.set('query', 'test');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Search")
q := baseURL.Query()
q.Set("query", "test")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Search")
uri.query = URI.encode_www_form({
"query" => "test"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/tfl.gov.uk/v1/Search?" . http_build_query([
"query" => "test"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));Gets a list of StopPoints within {radius} by the specified criteria
Hover any highlighted part to learn what it does
curl -X GET "https://api.apis.guru/v2/specs/tfl.gov.uk/v1/StopPoint?modes=example&radius=1&stopTypes=example&categories=example&returnLines=true&location.lat=1&location.lon=1&useStopPointHierarchy=true"
import requests
params = {
"modes": "example",
"radius": "1",
"stopTypes": "example",
"categories": "example",
"returnLines": "true",
"location.lat": "1",
"location.lon": "1",
"useStopPointHierarchy": "true"
}
response = requests.get(
"https://api.apis.guru/v2/specs/tfl.gov.uk/v1/StopPoint",
params=params,
)
print(response.json())const url = new URL('https://api.apis.guru/v2/specs/tfl.gov.uk/v1/StopPoint');
url.searchParams.set('modes', 'example');
url.searchParams.set('radius', '1');
url.searchParams.set('stopTypes', 'example');
url.searchParams.set('categories', 'example');
url.searchParams.set('returnLines', 'true');
url.searchParams.set('location.lat', '1');
url.searchParams.set('location.lon', '1');
url.searchParams.set('useStopPointHierarchy', 'true');
const response = await fetch(url);
const data = await response.json();
console.log(data);package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
baseURL, _ := url.Parse("https://api.apis.guru/v2/specs/tfl.gov.uk/v1/StopPoint")
q := baseURL.Query()
q.Set("modes", "example")
q.Set("radius", "1")
q.Set("stopTypes", "example")
q.Set("categories", "example")
q.Set("returnLines", "true")
q.Set("location.lat", "1")
q.Set("location.lon", "1")
q.Set("useStopPointHierarchy", "true")
baseURL.RawQuery = q.Encode()
targetURL := baseURL.String()
req, _ := http.NewRequest("GET", targetURL, nil)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}require "net/http"
require "json"
uri = URI("https://api.apis.guru/v2/specs/tfl.gov.uk/v1/StopPoint")
uri.query = URI.encode_www_form({
"modes" => "example",
"radius" => "1",
"stopTypes" => "example",
"categories" => "example",
"returnLines" => "true",
"location.lat" => "1",
"location.lon" => "1",
"useStopPointHierarchy" => "true"
})
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == "https"
req = Net::HTTP::Get.new(uri)
res = http.request(req)
puts JSON.parse(res.body)<?php
$url = "https://api.apis.guru/v2/specs/tfl.gov.uk/v1/StopPoint?" . http_build_query([
"modes" => "example",
"radius" => "1",
"stopTypes" => "example",
"categories" => "example",
"returnLines" => "true",
"location.lat" => "1",
"location.lon" => "1",
"useStopPointHierarchy" => "true"
]);
$opts = ["http" => [
"method" => "GET",
]];
$ctx = stream_context_create($opts);
$res = file_get_contents($url, false, $ctx);
print_r(json_decode($res, true));Postman Setup Guide
- See official documentation for authentication and setup.
What can you build with Transport for London Unified API?
Transport for London Unified API is a Data API. Developers commonly use data APIs for:
- enriching your app with third-party datasets
- building data pipelines and ETL workflows
- querying and searching large datasets
- powering research, analysis, and reporting tools
- syncing reference data into your own systems
No authentication required. This API is open — no signup or key needed. Ideal for quick prototypes and public-facing features. Transport for London Unified API is free to use, making it a low-risk choice to experiment with.
New to APIs? Read our beginner's guide · Learn about API keys · What is REST?