INEapy — Acceso a datos del INE de España
Instalación
pip install ineapy pandas
Dependencias: dlt, pydantic, pandas. No requiere API key (API pública del INE).
Arquitectura
INEapy
├── INEWrapper (bajo nivel) → requests a servicios.ine.es, JSON crudo
│ └── Usa dlt RESTClient + PageNumberPaginator
└── INEConsultor (alto nivel) → métodos simples, salidas listas para pandas
└── Parsea respuestas, devuelve dicts con timestamps y metadata
APIs base
- Wrapper:
https://servicios.ine.es/wstempus/js/{ES|EN}/ - Catálogo: https://www.ine.es/dyngs/INEbase/en/listaoperaciones.htm
- Doc API: https://www.ine.es/dyngs/DAB/index.htm?cid=1099
INEConsultor — Interfaz recomendada
from ineapy import INEConsultor
c = INEConsultor() # Español (default)
c_en = INEConsultor(language="EN") # Inglés
Listar operaciones disponibles
ops = c.list_operations() # Todas
ops = c.list_operations(filter_geo=0) # Solo nacional
ops = c.list_operations(filter_geo=1) # Solo CCAA
# → [{'id_operation': 25, 'cod_operation': 'IPC', 'name_operation': '...'}]
Operaciones estadísticas más útiles
| Código | Nombre | Variables comunes |
|---|---|---|
IPC |
Índice de Precios de Consumo | 349=Total Nacional, 762=Grupos ECOICOP, 3=Tipo dato |
IPCA |
IPC Armonizado | Mismas que IPC |
EPA |
Encuesta de Población Activa | Desempleo, empleo |
PIB / CNTR |
Contabilidad Nacional | PIB nominal/real |
IPI |
Índice de Producción Industrial | Por sector |
IPRI |
Índices de Precios Industriales | Por sector |
EPOBA |
Población actual | Provincias, sexo |
CP |
Cifras de Población | Provincias, sexo |
EEE:IND |
Estadística Empresas Industriales | Sector |
ICN |
Cifras de Negocios Industria | Por sector |
Obtener info de una operación
info = c.get_operation_info("IPC")
# → {'id_operation': 25, 'cod_operation': 'IPC', 'name_operation': 'Índice de Precios de Consumo (IPC)'}
Listar variables de una operación
variables = c.list_variables("IPC")
# → [{'id_variable': 349, 'name_variable': 'Total Nacional'}, ...]
Listar filtros disponibles
# Todos los filtros de una operación
filters = c.list_filters_from_operation("IPC")
# → [{'id_variable': 3, 'name_variable': 'Tipo de dato', 'id_value': 74, 'name_value': 'Variación anual'}]
# Valores de una variable específica
vals = c.list_filters_from_variable_operation("IPC", "349")
# → [{'id_variable': 349, 'id_value': 16473, 'name_value': 'Total Nacional'}]
# Todas las variables del sistema
all_vars = c.list_variables()
Periodicidades conocidas
p = c.list_periodicities()
# → [{'id': 1, 'name': 'Mensual'}, {'id': 12, 'name': 'Anual'}, ...]
| ID | Nombre |
|---|---|
| 0 | Al Detalle |
| 1 | Mensual |
| 2 | Bimestral |
| 3 | Trimestral |
| 4 | Cuatrimestral |
| 6 | Semestral |
| 7 | Semanal |
| 12 | Anual |
| 30 | Diario |
| 100 | Sin periodicidad |
Obtener datos — get_series_data (serie conocida)
# Si ya conoces el código de serie
data = c.get_series_data("IPC318622", nult=12)
# → [{'cod_serie': 'IPC318622', 'name_serie': '...', 'timestamp': Timestamp, 'year': 2025, 'value': 2.7, ...}]
# Por rango de fechas
data = c.get_series_data("IPC318622", date="20240101:20241231")
Obtener datos — get_operation_data (con filtros)
# IPC: Variación anual, Total Nacional, Índice general, últimos 6 meses
data = c.get_operation_data(
cod_operation='IPC',
filters=['349:16473', '762:304092'], # Total Nacional + Índice general
p=1, # Mensual
nult=6
)
# → [{'cod_serie': 'IPC318622', 'name_serie': '...', 'timestamp': Timestamp, 'value': 2.7, ...}]
Filtros IPC más usados:
349:16473→ Total Nacional762:304092→ Índice general (CPI total)3:74→ Variación anual (índice de variación)3:83→ Índice (valor absoluto)3:84→ Variación mensual3:85→ Media anual
Obtener datos de una tabla
# Listar tablas de una operación
tables = c.list_tables_from_operation("IPC")
# → [{'id_table': 24077, 'name_table': 'Índice general nacional...', ...}]
# Obtener datos de una tabla
data = c.get_table_data("24077", nult=12)
# Filtros de una tabla
filters = c.list_filters_from_table("24077")
Obtener datos por metadata (método flexible)
data = c.get_operation_data(
cod_operation='IPC',
filters=['349:16473', '762:304092'], # Total Nacional + Índice general
p=1,
date="20240101:20241231" # O nult=N
)
INEWrapper — Acceso bajo nivel
from ineapy import INEWrapper
wrapper = INEWrapper() # ES
wrapper_en = INEWrapper(language="EN")
Parámetros comunes
det(int): Nivel de detalle — 0=básico, 1=intermedio, 2=completotip(str): Tipo respuesta — ""=normal, "A"]=friendly, "M"]=metadata, "AM"]=friendly+metadatanult(int): Últimos N datosdate(str): Rango fechas"yyyymmdd:yyyymmdd"page(int): Número de páginafilters(list): Filtros["id_variable:id_value"]p(int): Periodicidad (ver tabla arriba)
Métodos Wrapper — Operaciones
r = wrapper.get_available_operations(det=0, tip="") # Lista operaciones
r = wrapper.get_operation("IPC", det=0, tip="M") # Info operación
r = wrapper.get_operation_tables("IPC", det=2, tip="M") # Tablas de operación
Métodos Wrapper — Series
r = wrapper.get_series("IPC318622", det=1, tip="M") # Info serie
r = wrapper.get_series_data("IPC318622", nult=12) # Datos serie
r = wrapper.get_series_values("IPC318622", det=1) # Valores serie
r = wrapper.get_operation_series("IPC", det=1, tip="M") # Series de operación (página)
all_series = wrapper.get_operation_series_all_pages("IPC", det=0) # Todas las series
Métodos Wrapper — Metadata
r = wrapper.get_operation_metadata_series("IPC", filters=["349:16473"], p=1, page=1)
all = wrapper.get_operation_metadata_series_all_pages("IPC", filters=["349:16473"], p=1)
r = wrapper.get_metadata_operation_data("IPC", filters=["349:16473"], p=1, nult=6)
Métodos Wrapper — Variables
r = wrapper.get_variables(det=0) # Todas las variables
r = wrapper.get_variable_values("115", det=1) # Valores de variable
r = wrapper.get_operation_variables("IPC", det=1) # Variables de operación
r = wrapper.get_operation_variable_values("115", "IPC") # Valores variable en operación
Métodos Wrapper — Tablas
r = wrapper.get_table("24077", det=2)
r = wrapper.get_table_data("24077", nult=12)
r = wrapper.get_table_series("24077", det=0, tip="M")
r = wrapper.get_table_groups("24077", det=2)
r = wrapper.get_table_group_values("24077", "1", det=1)
Métodos Wrapper — Publicaciones
r = wrapper.get_publications(det=0)
r = wrapper.get_operation_publications("IPC", det=0)
r = wrapper.get_publication_date("1", det=0)
Métodos Wrapper — Periodicidades
r = wrapper.get_periodicities() # Se llama en __init__, caché en self.periodicities
Errores comunes y pitfalls
Periodicidad inválida:
pdebe ser uno de los IDs de periodicidad (0,1,2,3,4,6,7,12,13,14,30,31,100,103-113). El error indica las válidas.Sin
nultnidate:get_series_datayget_operation_datarequieren al menos uno. Siempre pasarnult=Nodate="yyyymmdd:yyyymmdd".Filtros formato: Deben ser
"id_variable:id_value"(strings). Ej:"349:16473". Los IDs son numéricos pero se pasan como strings.Respuesta truncada del INE: La API del INE a veces devuelve arrays JSON incompletos (sin cerrar
]). El wrapper lo corrige automáticamente con__solve_errors_in_response.Serie completa sin filtros puede ser masiva:
list_series_from_operation("IPC")sin filtros puede tardar o agotar memoria. Usar filtros siempre que sea posible.get_operation_datavsget_series_data:get_series_data(cod_serie)→ cuando ya conoces el código de serieget_operation_data(cod_op, filters, p)→ cuando quieres datos filtrados por variables
Metadata de variable: Los IDs de variables y valores cambian entre operaciones. Siempre consultar
list_filters_from_variable_operation(op, var)primero.El INEWrapper retorna objetos
Responsede requests. Hay que hacer.json()para obtener los datos.El INEConsultor retorna listas de dicts parseados. Ya incluye
pd.to_datetime()en timestamps.Multi-idioma: INEWrapper e INEConsultor soportan
language="ES"(default) ylanguage="EN".
Ejemplo completo: IPC mensual España
from ineapy import INEConsultor
import pandas as pd
c = INEConsultor()
# 1. Verificar operación existe
info = c.get_operation_info("IPC")
print(f"Operación: {info['name_operation']}")
# 2. Ver variables disponibles
variables = c.list_variables("IPC")
print("Variables:", [v['name_variable'] for v in variables])
# 3. Ver valores de Total Nacional
vals = c.list_filters_from_variable_operation("IPC", "349")
print("Valores:", vals)
# 4. Obtener datos IPC variación anual, total nacional, índice general, mensual, últimos 12
data = c.get_operation_data(
cod_operation='IPC',
filters=['349:16473', '762:304092'],
p=1, # Mensual
nult=12
)
# 5. Convertir a DataFrame
df = pd.DataFrame(data)
print(df[['timestamp', 'year', 'period', 'value', 'name_serie']].head(10))
# 6. Filtrar solo variación anual
df_anual = df[df['name_serie'].str.contains('Variación anual')]
print(df_anual[['timestamp', 'value']])
Ejemplo completo: datos de tabla
from ineapy import INEConsultor
c = INEConsultor()
# Listar tablas de IPC
tables = c.list_tables_from_operation("IPC")
print(f"Tablas IPC: {len(tables)}")
for t in tables[:5]:
print(f" {t['id_table']}: {t['name_table']}")
# Obtener datos de una tabla específica
data = c.get_table_data("24077", nult=12)
print(f"Datos tabla: {len(data)} puntos")
Nota sobre la API directa del INE
Si se necesita más control o la librería no cubre algún endpoint, se puede usar la API REST directa:
GET https://servicios.ine.es/wstempus/js/ES/{FUNCION}/{INPUT}?parametros
Ejemplo:
curl "https://servicios.ine.es/wstempus/js/ES/DATOS_SERIE/IPC318622?nult=5"
La librería ineapy encapsula esta API con validación, paginación y manejo de errores.
Comparativa de alternativas
- es-ine/ineapir — wrapper R oficial del API INE, con endpoints portables entre lenguajes y una petición HTTP base común; útil si el consumo se hace desde R o se quiere la semántica oficial.