spanish-cities-info
v2.4.2
Published
8,132 Spanish municipalities verified against official INE data. Search by name, province, INE code, or radius (km). Modular imports by province/community. Postal codes available as an optional separate import. TypeScript, ~330KB (gzip: 125KB) for the mai
Maintainers
Readme
spanish-cities-info
Listado completo de los municipios de España (8.132, verificado contra el INE) con funciones para consultarlos: buscar por código INE, por nombre, por provincia, por isla, listar comunidades autónomas, encontrar municipios dentro de un radio en km de otro, y consultar códigos postales (import opcional, aparte del dataset principal).
Tipo City
{
name: 'Ferrol',
ineCode: '15036',
province: 'A Coruña',
community: 'Galicia',
latitude: 43.5098,
longitude: -8.2704
}
islandes opcional. Solo está presente en los 155 municipios de Illes Balears, Las Palmas y Santa Cruz de Tenerife (ej.island: 'Gran Canaria'). En el resto de España (incluida la España peninsular, Ceuta y Melilla) la claveislandno existe en el objeto — no esnullni"".
latitude/longitudeson el centroide geométrico del término municipal completo, no el centro urbano ni un punto de referencia histórico. En municipios grandes o de forma irregular pueden quedar a varios km del núcleo de población — verificado hasta ~7,5 km en casos como Murcia, consistente en una muestra de control de 26 municipios contra Wikipedia/geodatos.net. No es un error si al comparar visualmente contra Google Maps el punto no cae exactamente sobre el pueblo.
Cityno incluye códigos postales. Es un import aparte (spanish-cities-info/postal-codes) precisamente para no cargar ese dato en quien no lo necesita — ver la sección Códigos postales (import opcional).
Instalación
npm install spanish-cities-infoUso
import {
getAllCities,
getCityByCityCode,
getCityByName,
getCitiesByProvince,
getCitiesInRange,
getProvinces,
getCommunities,
getCitiesByCommunity,
getCitiesByIsland,
} from 'spanish-cities-info';getAllCities()
Devuelve los 8.132 municipios, ordenados alfabéticamente por nombre.
getAllCities();
// [{ name: 'A Baña', ineCode: '15007', province: 'A Coruña', community: 'Galicia', latitude: 42.9634, longitude: -8.7529 }, ...]getCityByCityCode(ineCode)
Busca un municipio por su código INE (5 dígitos). Devuelve undefined si no existe.
getCityByCityCode('15036');
// { name: 'Ferrol', ineCode: '15036', province: 'A Coruña', community: 'Galicia', latitude: 43.5098, longitude: -8.2704 }getCityByName(name)
Busca municipios cuyo nombre contenga el texto indicado (no distingue mayúsculas/minúsculas ni tildes). Devuelve [] si no hay coincidencias.
getCityByName('Ferrol');
// [{ name: 'Ferrol', ineCode: '15036', province: 'A Coruña', community: 'Galicia', latitude: 43.5098, longitude: -8.2704 }]
getCityByName('almeria');
// [{ name: 'Alhama de Almería', ... }, { name: 'Almería', ineCode: '04013', province: 'Almería', community: 'Andalucía', latitude: 36.8757, longitude: -2.3423 }, { name: 'Huércal de Almería', ... }]getCitiesByProvince(province)
Todos los municipios de una provincia. Útil para un select en cascada en un formulario. Devuelve [] si la provincia no existe.
getCitiesByProvince('Melilla');
// [{ name: 'Melilla', ineCode: '52001', province: 'Melilla', community: 'Melilla', latitude: 35.291, longitude: -2.9505 }]getCitiesInRange(referenceCity, rangeKm)
Municipios dentro de un radio en km de una ciudad de referencia (no incluye la propia ciudad de referencia). Devuelve [] si la ciudad de referencia no existe.
getCitiesInRange('Ferrol', 10).map((c) => c.name);
// ['Ares', 'Mugardos', 'Narón']referenceCity también acepta el código INE de 5 dígitos en vez del nombre, para desambiguar
entre municipios con el mismo nombre en provincias distintas (ej. "Sada" existe tanto en
A Coruña como en Navarra):
getCitiesInRange('15036', 10).map((c) => c.name);
// ['Ares', 'Mugardos', 'Narón'] — equivalente, usando el código INE de FerrolgetProvinces()
Listado de las 52 provincias, ordenado alfabéticamente.
getProvinces();
// ['A Coruña', 'Alacant', 'Albacete', 'Almería', 'Araba', ...]getCommunities()
Listado de las 19 comunidades y ciudades autónomas, sin duplicados y ordenado alfabéticamente.
getCommunities();
// ['Andalucía', 'Aragón', 'Asturias', 'Canarias', 'Cantabria', ...]getCitiesByCommunity(community)
Todos los municipios de una comunidad autónoma. Devuelve [] si la comunidad no existe.
getCitiesByCommunity('Melilla');
// [{ name: 'Melilla', ineCode: '52001', province: 'Melilla', community: 'Melilla', latitude: 35.291, longitude: -2.9505 }]getCitiesByIsland(island)
Todos los municipios de una isla. Solo aplica a los 155 municipios de Illes Balears, Las
Palmas y Santa Cruz de Tenerife — el resto de España (incluida la España peninsular,
Ceuta y Melilla) no tiene este dato, así que su City.island es undefined. Devuelve
[] si la isla no existe o no tiene municipios.
getCitiesByIsland('Menorca');
// [{ name: 'Alaior', ineCode: '07002', province: 'Illes Balears', community: 'Illes Balears', island: 'Menorca', latitude: 39.9339, longitude: 4.1403 }, ...]Islas disponibles: Mallorca, Menorca, Eivissa, Formentera, Gran Canaria,
Fuerteventura, Lanzarote, Tenerife, La Palma, La Gomera, El Hierro.
Imports modulares
Si solo necesitas los municipios de una provincia o comunidad autónoma, puedes importar
directamente esa zona sin cargar el dataset completo (8.132 municipios). Cada import
modular es autocontenido: un bundler que resuelva spanish-cities-info/provincias/lugo
solo incluye los municipios de Lugo, no el resto de España.
import { cities } from 'spanish-cities-info/provincias/lugo';
// 67 municipios de Lugo
import { cities } from 'spanish-cities-info/comunidades/galicia';
// 313 municipios: A Coruña + Lugo + Ourense + PontevedraEl slug es el nombre de la provincia/comunidad en minúsculas, sin tildes ni ñ, con
espacios sustituidos por guiones — por ejemplo getProvinces() devuelve 'A Coruña'
y el import correspondiente es spanish-cities-info/provincias/a-coruna;
getCommunities() devuelve 'País Vasco' y su import es
spanish-cities-info/comunidades/pais-vasco.
Códigos postales (import opcional)
Los códigos postales no están en City ni en el import principal — viven en su
propio subpath, igual que los imports por provincia/comunidad. Así, quien no los
necesita no paga su peso: el mapa completo (8.132 municipios) pesa ~227 KB sin
comprimir / ~52 KB gzip, frente a los ~330 KB / ~125 KB gzip del import principal. Si
importas solo spanish-cities-info, ese coste no existe en tu bundle.
import { getPostalCodes } from 'spanish-cities-info/postal-codes';
getPostalCodes('15036');
// ['15401', '15402', '15403', '15404', '15405', '15406', '15590', '15592', '15593', '15594', '15595']
getPostalCodes('00000'); // código INE inexistente
// []También expone el mapa completo ineCode → postalCodes[], por si necesitas recorrerlo
en vez de consultar municipio a municipio:
import { postalCodesByIneCode } from 'spanish-cities-info/postal-codes';
postalCodesByIneCode['15036'];
// ['15401', '15402', ...]Si quieres un City con sus códigos postales incluidos, combínalos tú mismo — el
paquete no los devuelve ya fusionados, precisamente para no forzar esa carga a quien no
lo pide:
import { getCityByCityCode } from 'spanish-cities-info';
import { getPostalCodes } from 'spanish-cities-info/postal-codes';
const city = { ...getCityByCityCode('15036'), postalCodes: getPostalCodes('15036') };La cobertura puede tener huecos en zonas rurales. La fuente es el callejero censal del INE, que asocia códigos postales a tramos de vía concretos — si el INE no tiene ningún tramo censado bajo un código INE de municipio, ese código postal simplemente no aparece en la fuente. Esto afecta sobre todo a parroquias y núcleos rurales dispersos dentro de municipios grandes (verificado en una muestra de control: Ferrol y Folgoso do Courel tienen menos CP en este dataset que en agregadores de terceros que cruzan fuentes adicionales). No es un error del paquete ni del dataset origen, es una propiedad conocida de la fuente oficial. Si un municipio no tiene ningún CP conocido, su clave no está presente en
postalCodesByIneCodeygetPostalCodesdevuelve[]— en la práctica, a fecha de esta versión, los 8.132 municipios tienen al menos un CP conocido.Algunos códigos postales pertenecen administrativamente a un municipio distinto del que sirven (ej.
28523, bajo Madrid en este dataset, es en realidad la oficina de Rivas-Vaciamadrid) — son núcleos de población partidos entre términos municipales con cartería asignada de forma no estrictamente administrativa, un fenómeno real y documentado del sistema postal español, no un error de cruce de datos.
Datos
Municipios y códigos INE: Instituto Nacional de Estadística, a fecha 01-01-2026. Comunidades autónomas: lookup provincia → comunidad verificado contra el INE (19 comunidades y ciudades autónomas). Islas: codislas.xlsx del INE, a fecha 01-01-2025 (155 municipios de Illes Balears, Las Palmas y Santa Cruz de Tenerife), cruzado por código INE contra cities.json.
Coordenadas (latitude/longitude): centroides geométricos del dataset georef-spain-municipio ("Municipalities - Spain") de Opendatasoft, licencia CC BY 4.0, con datos de base del Instituto Geográfico Nacional (IGN). Cruzado por código INE contra cities.json.
Códigos postales: regi-es/ds-codigos-postales-ine-es (edición callejero 2026-07, diccionario 2026), que a su vez elabora los datos a partir del Callejero del Censo Electoral y el diccionario de municipios, ambos del INE. Cruzado por código INE contra cities.json (8.132/8.132 municipios con coincidencia). Se descarta el código 28000 (dato inválido confirmado, no es un CP real de entrega de Correos); el resto de códigos "cross-municipio" (ej. un CP que administrativamente sirve a un municipio distinto del que aparece en el dataset) se conserva tal cual, ver nota más arriba. regi-es/ds-codigos-postales-ine-es no es un fork de inigoflores/ds-codigos-postales-ine-es — es un dataset independiente, mantenido por otra organización, que regenera los datos de ediciones más recientes del INE mientras conserva compatibilidad de formato (mismo CSV) con el proyecto original. Datos derivados del INE, reutilizados conforme a la Ley 37/2007; fuente: sitio web del INE, www.ine.es.
El INE publica actualizaciones de este listado periódicamente (normalmente cada enero, a veces también en julio). Cuando hay una nueva versión, se descarga el fichero oficial y se compara contra el dataset actual con scripts/reconcile_ine.py para detectar altas, bajas y cambios de nombre antes de actualizar el paquete.
Contribución
Si encuentras algún error en los datos o echas en falta algo, abre un issue.
Las correcciones de datos se validan contra la fuente oficial del INE
(scripts/reconcile_ine.py) antes de aplicarse.
Para cambios en el código, pull requests bienvenidos.
