Estaba scrolleando a las 11pm cuando vi el proyecto: cada subte de Nueva York asignado a un instrumento, tocando una nota según su posición en tiempo real. El mapa de Manhattan convertido en partitura generativa. Inmediatamente cerré la mitad de las tabs abiertas y abrí una terminal.
¿Qué pasaría con el Sarmiento? ¿Con el Mitre? ¿Con el Belgrano Sur que siempre está en el olvido de todo el mundo excepto de la gente que lo necesita para trabajar?
No como ejercicio nostálgico. Como pregunta técnica real: ¿tenemos datos de posición en tiempo real? ¿Qué tan abiertos son? Pasé la tarde siguiente investigando, escribiendo código, chocando contra paredes y llegando a conclusiones que dicen mucho más sobre infraestructura pública argentina que sobre trenes o música.
Te cuento todo.
Datos abiertos, transporte y creatividad: el proyecto que me desveló
El proyecto original —si no lo viste— usa la API pública del MTA de Nueva York. Cada línea tiene un feed GTFS-RT (General Transit Feed Specification, Realtime). Posición GPS de cada tren. Actualización cada 30 segundos. Disponible sin autenticación, sin cuotas ridículas, sin formularios de solicitud de acceso.
El código base es casi trivial:
// Fetch del feed GTFS-RT del MTA — gratuito, sin auth
const response = await fetch(
'https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs'
);
// Decodificás el protobuf
const feed = GtfsRealtimeBindings.transit_realtime.FeedMessage.decode(
new Uint8Array(await response.arrayBuffer())
);
// Cada entidad es un vehículo con posición lat/lng
feed.entity.forEach(entity => {
if (entity.vehicle?.position) {
const { latitude, longitude } = entity.vehicle.position;
// Mapeás coordenadas a nota musical — simple y elegante
const nota = mapCoordsToNote(latitude, longitude);
playNote(nota, entity.vehicle.trip.routeId);
}
});
Limpio. Directo. Funciona en diez minutos desde que encontrás la documentación.
Ahora bien. Me pregunté: ¿existe algo equivalente para Trenes Argentinos?
El descent into madness: buscando datos de posición en tiempo real
Empecé por donde empezaría cualquiera: Google. "API Trenes Argentinos tiempo real". "GTFS Buenos Aires trenes". "SUBE API pública posición".
Primer hallazgo: Argentina tiene datos GTFS. Datos del Gobierno Nacional en datos.gob.ar. Bien. ¿Qué hay ahí?
# Descargando el dataset de transporte ferroviario
curl -L "https://datos.gob.ar/dataset/transporte-modelo-de-datos-transporte-publico-pasajeros-base-datos-gtfs" \
-o gtfs_argentina.zip
unzip gtfs_argentina.zip
ls -la
# stops.txt ✓
# routes.txt ✓
# trips.txt ✓
# stop_times.txt ✓
# shapes.txt... ausente para ferroviario
# vehicle_positions.pb... no existe
Ahí está el primer problema. Tenés GTFS estático. O sea: horarios, paradas, recorridos. La infraestructura básica del sistema. Pero GTFS-RT —la parte Realtime, la que te dice dónde está cada tren ahora mismo— no existe en ninguna forma pública que yo haya podido encontrar.
Seguí cavando.
La API de Trenes Argentinos: lo que encontré y lo que no
Hay una app oficial de Trenes Argentinos. La app muestra posición de formaciones en algunos ramales. Eso significa que en algún lugar existe un endpoint con esa info.
# Interceptando tráfico de la app con mitmproxy
# (completamente legal para uso personal/investigación)
import mitmproxy
# Lo que encontré después de 40 minutos de interceptar requests:
# POST https://api.transp.gob.ar/v2/... → 401 sin token
# GET https://[endpoint-privado]/formaciones → requiere OAuth2
# WebSocket a servidor interno → sin documentación pública
# No hay forma de autenticarse sin ser un organismo gubernamental
# o tener un convenio firmado con el Ministerio de Transporte
Los datos existen. No son públicos.
Acá fue donde me acordé de algo que escribí hace unas semanas sobre cómo los benchmarks de agentes de IA están rotos: el problema no siempre es técnico. A veces es de incentivos, de cultura, de qué cosas se consideran valiosas. Los datos de posición de trenes son un activo. En NY decidieron que ese activo vale más abierto que cerrado. Acá todavía no llegamos a esa conclusión.
SUBE: ¿y si vamos por otro lado?
Segunda idea: usar datos de SUBE. Si no puedo saber dónde están los trenes, ¿puedo inferir movimiento a partir de validaciones?
La respuesta es más interesante.
# Intentando acceder a datos abiertos de SUBE
import requests
# Hay una API documentada en: https://www.argentina.gob.ar/sube/desarrolladores
# Lo que dice la documentación:
# - Podés consultar saldo
# - Podés ver movimientos de tu propia tarjeta
# - NO podés ver datos agregados por línea o estación en tiempo real
base_url = "https://api.sube.gob.ar/v1"
# Este endpoint SÍ existe y funciona con tu DNI/CUIL:
response = requests.get(
f"{base_url}/tarjetas/movimientos",
headers={"Authorization": f"Bearer {mi_token}"}
)
# Datos de tu tarjeta. Nada más.
# Datos agregados anonimizados por estación: no disponibles públicamente
# Flujo de pasajeros en tiempo real: no disponible
# Cualquier cosa útil para el proyecto: no disponible
Existe una API de SUBE. Sirve para que cada usuario vea sus propios datos. Para hacer algo creativo o analítico con datos del sistema completo, no sirve.
Lo que sí pude hacer: una versión degradada (y honesta)
Después de todo esto, decidí construir algo con lo que realmente tenía. No el proyecto que quería. El proyecto que era posible.
// mi-tren-musical.js
// Versión honesta: usa GTFS estático + horarios programados
// No es tiempo real — es una simulación basada en schedule
import * as Tone from 'tone';
import { parse } from 'csv-parse/sync';
import fs from 'fs';
// Cargo stop_times.txt del GTFS estático argentino
const stopTimes = parse(
fs.readFileSync('./gtfs/stop_times.txt'),
{ columns: true }
);
// Mapeo de líneas a instrumentos — acá me divertí
const instrumentos = {
'Sarmiento': new Tone.Synth({ oscillator: { type: 'sawtooth' } }).toDestination(),
'Mitre': new Tone.Synth({ oscillator: { type: 'sine' } }).toDestination(),
'Belgrano_Sur': new Tone.Synth({ oscillator: { type: 'square' } }).toDestination(),
'Roca': new Tone.Synth({ oscillator: { type: 'triangle' } }).toDestination(),
'San_Martin': new Tone.FMSynth().toDestination(),
'Belgrano_Norte': new Tone.AMSynth().toDestination(),
'Urquiza': new Tone.MetalSynth().toDestination(),
};
// Escala pentatónica — suena bien con cualquier combinación
// (tip robado de un foro de música generativa)
const escala = ['C4', 'D4', 'E4', 'G4', 'A4', 'C5', 'D5', 'E5'];
function horaActualASegundos() {
const ahora = new Date();
return ahora.getHours() * 3600 + ahora.getMinutes() * 60 + ahora.getSeconds();
}
function gtfsHoraASegundos(horaStr) {
// GTFS permite horas > 24 para viajes que pasan medianoche
const [h, m, s] = horaStr.split(':').map(Number);
return h * 3600 + m * 60 + s;
}
// Buscá qué trenes deberían estar en movimiento ahora
function trenesActivosAhora(linea) {
const ahora = horaActualASegundos();
return stopTimes.filter(st => {
const salida = gtfsHoraASegundos(st.departure_time);
const llegada = gtfsHoraASegundos(st.arrival_time);
// Tren "activo" si está entre salida de parada anterior y llegada a siguiente
return salida <= ahora && llegada >= ahora;
});
}
// Loop principal — se ejecuta cada 5 segundos
Tone.Transport.scheduleRepeat(() => {
Object.entries(instrumentos).forEach(([linea, synth]) => {
const activos = trenesActivosAhora(linea);
if (activos.length > 0) {
// La nota depende de cuántos trenes hay en movimiento
// Más trenes = nota más aguda
const indice = Math.min(activos.length, escala.length - 1);
synth.triggerAttackRelease(escala[indice], '8n');
}
});
}, '5s');
Tone.Transport.start();
console.log('🚂 Escuchando los trenes de Buenos Aires (versión schedule)...');
console.log('⚠️ Esto es basado en horarios programados, no posición real');
console.log(' Porque Argentina no tiene GTFS-RT público. Todavía.');
Funciona. Suena. Es honesto sobre sus limitaciones.
Lo más Belgrano Sur que encontré: cuando el GTFS dice que hay tres trenes en movimiento simultáneo, el synth cuadrado hace exactamente el ruido que imaginarías.
Los gotchas que nadie te cuenta sobre datos públicos argentinos
1. "Datos abiertos" no siempre significa "datos útiles".
Hay datasets en datos.gob.ar que están ahí como checkbox, no como recurso real. Última actualización: 2019. Formato: PDF. Coordenadas: en grados, minutos y segundos con coma decimal en vez de punto. Son datos abiertos técnicamente. Prácticamente, son papel mojado.
2. Las apps oficiales mienten con sus APIs.
Si la app muestra algo, los datos existen. Pero el gap entre "existe internamente" y "es accesible públicamente" es enorme, y acá ese gap es la norma, no la excepción.
3. GTFS estático desactualizado es peor que no tener datos.
Usé stop_times.txt de una versión del GTFS de hace varios meses. La mitad de los horarios del Belgrano Sur habían cambiado. Mi "simulación en tiempo real" tocaba notas para trenes que ya no existían en esos horarios. Tuve que agregar validación manual, que a su vez requería datos que tampoco estaban actualizados. Un loop kafkiano.
4. La comunidad llena el vacío, pero no de forma confiable.
Hay proyectos en GitHub de gente que hizo scraping de las apps oficiales. Algunos tienen meses sin mantenimiento. Otros usan tokens hardcodeados que ya expiraron — algo que, como revisé hace poco en PRs vibe-coded con keys expuestas, es un problema mucho más común de lo que parece y con consecuencias reales.
5. El problema no es técnico. Es cultural.
El MTA de Nueva York tiene GTFS-RT porque alguien decidió que los datos del transporte público son un bien público. Esa decisión no es técnica. Es política. Es filosófica. Y en Argentina esa decisión todavía no está tomada de forma consistente.
FAQ: Datos abiertos, transporte y creatividad con datos públicos
¿Existe alguna API oficial de Trenes Argentinos para desarrolladores externos?
No en forma pública y documentada. Hay endpoints usados por las apps oficiales pero requieren autenticación OAuth2 con credenciales que no se otorgan a desarrolladores individuales. Para acceso oficial necesitás un convenio con el Ministerio de Transporte, que existe pero está orientado a organismos, no a proyectos independientes.
¿Puedo usar datos GTFS de Argentina para hacer proyectos como el de Nueva York?
Podés usar el GTFS estático disponible en datos.gob.ar, que te da horarios, paradas y recorridos. Para replicar el proyecto de NY necesitás GTFS-RT (tiempo real con posición GPS), que no está disponible públicamente para el sistema ferroviario argentino. Podés hacer una versión basada en schedules, como hice yo, pero es una simulación, no datos en tiempo real.
¿Qué es GTFS-RT y por qué importa para proyectos creativos con datos de transporte?
GTFS-RT es la extensión en tiempo real del estándar GTFS. Provee tres feeds: posición de vehículos (donde está cada formación en este momento), alertas de servicio (demoras, cancelaciones) y actualizaciones de viaje (llegadas estimadas dinámicas). Para el tipo de proyecto creativo del que hablo, el feed de posición de vehículos es el que convierte datos de transporte en algo generativo y vivo. Sin él, estás trabajando con horarios estáticos.
¿Por qué Nueva York tiene estos datos abiertos y Argentina no?
Es una decisión política y cultural, no técnica. El MTA empezó a publicar GTFS-RT en 2011 después de años de presión de la comunidad tech de NYC y de legisladores locales. Hubo incluso demandas legales argumentando que los datos del transporte público pertenecen al público. En Argentina no hubo una presión equivalente sostenida, y la cultura de datos abiertos en el Estado todavía está en desarrollo. No es un problema de capacidad técnica — los datos existen, la decisión de abrirlos no se tomó.
¿Hay alternativas para obtener posición de trenes en Buenos Aires?
Algunas opciones parciales: 1) Scraping de la web de Trenes Argentinos (frágil, no confiable, potencialmente viola términos de uso), 2) Proyectos comunitarios como OpenStreetMap que tienen datos de infraestructura pero no posición en tiempo real, 3) APIs de colectivos — InfoBaeTe y apps de transporte tienen datos de algunas líneas pero con cobertura inconsistente. Para ferroviario en tiempo real real, hoy no hay una solución limpia y confiable disponible públicamente.
¿Vale la pena hacer proyectos creativos con datos públicos aunque sean limitados?
Absolutamente sí, y por una razón que va más allá del resultado: construir estos proyectos documenta los gaps. Cuando publicás "quise hacer X, los datos no me lo permitieron porque Y", estás generando evidencia pública de qué falta. Varios proyectos de la comunidad tech argentina terminaron siendo el empujón que necesitaban algunos datasets para abrirse. El proyecto imperfecto que comunica sus limitaciones honestamente tiene más valor que no hacer nada.
Conclusión: la partitura que no pude escribir (y lo que eso dice)
No pude hacer el proyecto que quería. El Sarmiento no tiene su instrumento asignado a posición GPS real. El Belgrano Sur no suena en tiempo real cuando pasa por Villa del Parque.
Lo que sí tengo es un mapa claro de por qué no: los datos existen, no son públicos, y esa decisión es cultural antes que técnica.
Me hace pensar en algo que me cruzó la semana pasada leyendo sobre la propuesta de usar IA para contribuir al kernel de Linux: la infraestructura de datos públicos es tan importante como la infraestructura técnica. Podés tener toda la creatividad del mundo — y hay gente con muchísima en la comunidad tech argentina — pero si la materia prima está cerrada, el producto final es siempre una aproximación.
Al mismo tiempo, me parece importante no quedarme en el lamento. La versión que construí con GTFS estático funciona. Suena. Muestra qué sería posible. Y ese gap entre "lo que es posible" y "lo que existe" es exactamente el tipo de presión que eventualmente abre datos.
La próxima vez que viajes en el Sarmiento y llegues tarde, acordate: en algún servidor del Estado hay un dato que dice exactamente dónde estabas. Ese dato no es tuyo. Todavía.
Si te animás a jugar con el código que compartí, o si encontraste alguna API que yo me perdí en mi investigación, contame. Genuinamente. Me encantaría estar equivocado sobre el estado de los datos abiertos de transporte en Argentina.
Este artículo fue publicado originalmente en juanchi.dev
Top comments (0)