API para desenvolvedores
Os mesmos datos que o mapa, en JSON. De balde, sen rexistro e sen clave. Úsaa na túa web, na túa app ou na túa investigación.
Nun minuto
- Enderezo base:
https://trenes.valfiguer.com/api/v1 - Só lectura (GET), respostas en JSON ou GeoJSON, en UTF-8 e comprimidas se as pides con gzip.
- CORS aberto: podes chamala desde o navegador, desde calquera dominio. Non usa cookies nin clave.
- Horas como marca Unix en segundos (
*_ts) e como ISO 8601 en UTC (*_at). - Especificación OpenAPI: /api/openapi.json · Consola interactiva: /api/docs
curl -s --compressed https://trenes.valfiguer.com/api/v1/trains | jq '.features | length'Condicións de uso
Os datos veñen de Renfe Data, FGC Dades Obertes e Open Data Euskadi (MovEuskadi), todos con licenza CC BY 4.0. Podes usalos para o que queiras, tamén con fins comerciais, se citas a fonte. Abonda cunha liña:
Datos: Renfe Data, FGC e MovEuskadi (CC BY 4.0) vía trenes.valfiguer.comNon é un sistema de seguridade. As posicións chegan con segundos ou minutos de atraso e poden faltar trens. Non a uses para decisións de seguridade nin a presentes como información oficial; a oficial é a de cada operador e Adif.
Límites e caché
- Ata 30 peticións por segundo por IP, con picos de 100. Por riba responde
429: agarda un segundo e téntao de novo. - As posicións renóvanse cada 15–20 s na orixe. Pedir
/trainsmáis dunha vez cada 5 s non trae nada novo. - As respostas grandes levan
ETag: envíaIf-None-Matche recibirás304sen corpo se non cambiou. - Se vas mover moito tráfico ou necesitas o histórico completo, escríbenos a info@valfiguer.com.
Como ler un tren
delay_s: atraso en segundos segundo o operador;nullse non o publica (FGC só di se vai en hora: miraflags).reported_at/age_s: cando se tomou a posición e a súa antigüidade ao xerar a resposta.stale: truese leva máis de 3 minutos sen actualizarse.flags: correccións ou avisos aplicados ao dato, por exemplo unha hora corrixida ou unha posición descartada por imposible.category:ld(alta velocidade e longa distancia),md(media distancia),cercaniasouotros(FGC e Metro Bilbao).
Rutas
Trens en circulación
GET/api/v1/trains
Todos os trens con posición publicada agora, como GeoJSON FeatureCollection, co estado de cada fonte en feeds.
Caché: 5 s, ETag · Probar
{
"type": "FeatureCollection",
"generated_at": "2026-11-01T08:12:30Z",
"generated_ts": 1793520750,
"attribution": "Fuentes: Renfe Data (data.renfe.com), FGC Dades Obertes … CC BY 4.0. …",
"feeds": [{ "id": "renfe_ld_positions", "ok": true, "stale": false, "data_age_s": 14 }],
"features": [{
"type": "Feature",
"id": "renfe_ld:<id>",
"geometry": { "type": "Point", "coordinates": [-3.6893, 40.4066] },
"properties": {
"source": "renfe_ld", "operator": "Renfe", "category": "ld",
"product": "AVE", "train_number": "00297", "nucleo": null,
"line_color": null, "origin": "Madrid-Puerta de Atocha", "destination": "Barcelona-Sants",
"status_text": "en", "stop_name": "Zaragoza-Delicias", "platform": "4",
"delay_s": 180, "reported_at": "2026-11-01T08:12:16Z", "age_s": 14,
"stale": false, "speed_kmh": 287, "bearing": 64, "flags": []
}
}]
}Un tren
GET/api/v1/trains/{id}
Un tren co seu percorrido recente (ata 80 posicións en track: lon, lat, hora) e o seu itinerario: paradas con hora programada e estimada (horario máis o atraso actual).
| Parámetro | En | Que é |
|---|---|---|
id | ruta | O id de /trains, por exemplo renfe_cercanias:1004D27203C4a. |
Caché: 5 s · Probar
{
"id": "renfe_ld:00297",
"properties": { "…": "como en /trains" },
"track": [[-3.6893, 40.4066, 1793520736]],
"itinerary": {
"method": "horario_mas_retraso_actual",
"delay_s": 180,
"stops": [{
"code": "71801", "name": "Barcelona-Sants",
"arrival_ts": 1793530800, "estimated_arrival_ts": 1793530980,
"state": "upcoming"
}]
}
}Un tren polo seu número
GET/api/v1/trains/numero/{número}
O mesmo que /trains/{id}, buscando polo número comercial que sae no billete ou no panel. Responde 404 se ese número non ten posición agora.
| Parámetro | En | Que é |
|---|---|---|
número | ruta | Número comercial, con ou sen ceros á esquerda. |
nucleo | consulta | Opcional. Distingue Cercanías de cidades distintas: Madrid, Barcelona, Valencia… |
Caché: 5 s · Probar
{ "id": "renfe_cercanias:1004D27704C5", "properties": { "…": "…" }, "track": [], "itinerary": null }Horario de hoxe dun tren
GET/api/v1/horario/numero/{número}
As saídas de hoxe dun número de tren segundo o calendario GTFS de Renfe, coas súas paradas e se está cancelado. Serve para trens que aínda non saíron.
| Parámetro | En | Que é |
|---|---|---|
número | ruta | Número comercial. |
nucleo | consulta | Opcional, como arriba. |
Caché: 30 s · Probar
{
"method": "horario_gtfs",
"runs": [{
"trip_id": "0029712026-11-01", "day": "2026-11-01", "cancelled": false,
"product": "AVE", "origin": "Madrid-Puerta de Atocha", "destination": "Barcelona-Sants",
"departure_ts": 1793520000, "arrival_ts": 1793530800,
"itinerary": { "stops": [] }
}]
}Panel dunha estación
GET/api/v1/stations/{código}
Trens das próximas dúas horas nunha estación: os que circulan, con hora estimada, e os que aínda non saíron segundo o horario de hoxe (state: scheduled). Inclúe a ficha da estación cando Adif a publica.
| Parámetro | En | Que é |
|---|---|---|
código | ruta | Código de estación de Renfe (ata 5 cifras), o mesmo de /stations. |
Caché: 10 s · Probar
{
"station": { "code": "18000", "name": "Madrid-Puerta de Atocha", "lat": 40.4066, "lon": -3.6893 },
"trains": [{
"id": null, "trip_id": "…", "state": "scheduled", "category": "cercanias",
"product": "C5", "train_number": "27704", "destination": "Humanes",
"planned_ts": 1793520660, "estimated_ts": null, "delay_s": null,
"cancelled": false, "terminates": false
}]
}Estacións
GET/api/v1/stations
Todas as estacións co seu código e nome, como GeoJSON de puntos.
Caché: 1 h, ETag · Probar
{ "type": "FeatureCollection", "features": [{ "geometry": { "type": "Point", "coordinates": [-3.6893, 40.4066] }, "properties": { "code": "18000", "name": "Madrid-Puerta de Atocha" } }] }Liñas
GET/api/v1/lines
Percorrido das liñas de Cercanías, FGC e Metro Bilbao coa súa cor oficial, como GeoJSON de liñas simplificadas a uns 15 m.
Caché: 1 h, ETag · Probar
{ "type": "FeatureCollection", "features": [{ "properties": { "nucleo": "Madrid", "line": "C5", "name": "Móstoles-El Soto - Humanes", "color": "#FFCB06", "text_color": "#000000" }, "geometry": { "type": "LineString", "coordinates": [] } }] }Puntualidade
GET/api/v1/puntualidad
Puntualidade diaria por liña e produto: viaxes, viaxes con atraso e suma de atrasos, a partir do último atraso publicado de cada tren.
| Parámetro | En | Que é |
|---|---|---|
dias | consulta | Días cara atrás, de 1 a 31 (7 por defecto). |
Caché: 5 min · Probar
{ "on_time_threshold_s": 300, "days": [{ "date": "2026-10-31", "partial": false, "groups": [{ "label": "C5", "nucleo": "Madrid", "trips": 412, "on_time": 371, "over_30": 2 }] }] }Avisos
GET/api/v1/alerts
Avisos activos de Cercanías publicados por Renfe, coas liñas ás que afectan.
Caché: 30 s · Probar
{ "alerts": [{ "id": "…", "text": "…", "start": "2026-11-01T05:00:00Z", "end": null, "lines": [{ "nucleo": "Madrid", "line": "C3" }] }] }Cancelacións
GET/api/v1/cancellations
Trens que Renfe dá por cancelados agora.
Caché: 30 s · Probar
{ "count": 1, "trains": [{ "trip_id": "…", "category": "md", "product": "MD", "train_number": "18073", "origin": "…", "destination": "…" }] }Estado
GET/api/v1/status
Resumo do servizo: número de trens, puntualidade do momento e saúde de cada fonte.
Caché: 10 s · Probar
{ "trains": { "total": 812, "fresh": 790, "by_category": { "ld": 120, "cercanias": 610 } }, "delay": { "known": 700, "on_time_share": 0.91 }, "cancelled": 11, "feeds": [{ "id": "renfe_ld_positions", "ok": true, "data_age_s": 14 }] }Exemplos
JavaScript, no navegador ou en Node 18+:
const res = await fetch("https://trenes.valfiguer.com/api/v1/trains");
const { features } = await res.json();
const late = features.filter((f) => (f.properties.delay_s ?? 0) > 600);
console.log(`${late.length} trens con máis de 10 min de atraso`);Python:
import httpx
board = httpx.get("https://trenes.valfiguer.com/api/v1/stations/18000").json()
for t in board["trains"][:5]:
print(t["product"], t["destination"], t["delay_s"])Mapa con MapLibre ou Leaflet: engade a resposta de /trains como fonte GeoJSON e actualízaa cada 15 s.
map.addSource("trenes", { type: "geojson", data: "https://trenes.valfiguer.com/api/v1/trains" });
setInterval(() => map.getSource("trenes").setData("https://trenes.valfiguer.com/api/v1/trains"), 15000);Versións
A v1 é estable: podemos engadir campos, pero non quitalos nin cambiar o seu significado sen publicar unha v2 e manter a v1 polo menos seis meses. O teu código debe ignorar os campos que non coñeza.
Máis sobre as fontes, a súa frecuencia e o rexistro histórico en Datos.
Widgets para a túa web
Un panel de saídas dunha estación ou os trens dunha liña, dentro da túa páxina. Actualízanse sós e axustan a súa altura ao contido. Pega o bloque onde queiras que apareza:
<div data-trenes-estacion="18000"></div>
<script src="https://trenes.valfiguer.com/embed.js" async></script>Unha liña: núcleo e liña, tal como aparecen no mapa, en minúsculas e con guións.
<div data-trenes-linea="madrid/c5"></div>
<div data-trenes-linea="rodalies-de-catalunya/r2-nord"></div>
<div data-trenes-linea="fgc/s1"></div>
<script src="https://trenes.valfiguer.com/embed.js" async></script>data-tema="claro"(claro) ou"oscuro"(escuro): fixa o tema. Sen el, segue o do visitante. O atributo e os seus valores quedan en castelán.data-filas="6": cantos trens mostrar (estación: 1–15, 6 por defecto; liña: 1–20, 8 por defecto).data-idioma="gl": idioma do widget (es,en,ca,euougl; castelán por defecto). O panel e o widget de pantalla de inicio tamén existen en cada idioma:/gl/panel/18000.- O código de estación é o de Renfe, o mesmo de /stations/{código} e do enderezo de cada páxina de estación.
- Se engades widgets despois de cargar a páxina (unha aplicación dunha soa páxina), chama a
window.TrenesEmbed.scan().
Sen JavaScript, cun iframe de altura fixa:
<iframe src="https://trenes.valfiguer.com/embed/estacion/18000?tema=claro&filas=5"
title="Próximos trens" loading="lazy"
style="width:100%;height:360px;border:0"></iframe>O pé do widget leva a atribución que piden as licenzas (Renfe Data, FGC e MovEuskadi, CC BY 4.0) e unha ligazón á páxina completa: non o tapes nin o quites. Só as rutas /embed/ se poden mostrar dentro doutras webs.
Panel a pantalla completa
Para unha televisión ou unha tableta nun vestíbulo, unha oficina ou unha cafetería: /panel/{código} mostra as próximas saídas en grande, con reloxo, actualízase cada 15 s, axusta o tamaño da letra á pantalla e, onde o navegador o permite, impide que a pantalla se apague.
https://trenes.valfiguer.com/panel/18000
https://trenes.valfiguer.com/panel/18000?tema=claro&filas=8Escuro por defecto; ?tema=claro para salas con moita luz. ?filas= admite de 3 a 20. Cada páxina de estación ten unha ligazón «Modo panel».
Cliente JavaScript
Un módulo pequeno, sen dependencias, para o navegador ou Node 18+. Tipos en /sdk/trenes.d.ts.
import { createClient } from "https://trenes.valfiguer.com/sdk/trenes.js";
const api = createClient(); // ou createClient({ baseUrl, timeoutMs, fetch })
const { features } = await api.trains();
const board = await api.station("18000"); // null se o código non existe
const runs = await api.schedule("00297");
const tren = await api.train(features[0].id);
const lineas = await api.lines();Tamén exporta cada función solta (trains, train, station, schedule, lines…). Un 404 devolve null; calquera outro erro lanza TrenesError co seu status. Para TypeScript, descarga o .d.ts xunto ao módulo ou copia os tipos que necesites.
Python 3.10+, só coa biblioteca estándar:
import json
import urllib.request
BASE = "https://trenes.valfiguer.com/api/v1"
def get(path: str):
req = urllib.request.Request(BASE + path, headers={"Accept": "application/json"})
with urllib.request.urlopen(req, timeout=10) as res:
return json.load(res)
board = get("/stations/18000")
print(board["station"]["name"])
for t in board["trains"][:8]:
atraso = "sen dato" if t["delay_s"] is None else f"{round(t['delay_s'] / 60)} min"
print(t["product"], t["train_number"], "→", t["destination"], atraso)
# Datos: Renfe Data, FGC e MovEuskadi (CC BY 4.0) vía trenes.valfiguer.comFeeds RSS
Avisos e cancelacións en formato RSS, para o teu lector de noticias ou para automatizar alertas. Pódense filtrar por núcleo e por liña con ?nucleo=madrid&linea=c5; cada páxina de liña ten ligazóns aos seus.
- /api/v1/feeds/avisos.xml: avisos activos de Cercanías e Rodalies.
- /api/v1/feeds/cancelaciones.xml: trens que Renfe marca como cancelados agora.
Reflicten o que Renfe publica nos seus datos abertos, cos mesmos ocos. Licenza CC BY 4.0. Os textos dos avisos están en castelán, tal como os publica Renfe.