Gob APIgeoportal.minetur.gob.es ↗
Query Spain's infoantenas geoportal for mobile base station locations, operators, frequency bands, and measured RF exposure levels via a two-endpoint REST API.
What is the Gob API?
This API exposes data from Spain's official infoantenas geoportal (geoportal.minetur.gob.es), covering mobile telephony base stations nationwide across two endpoints. Use search_stations to retrieve up to 1,000 stations within a WGS84 bounding box — each record includes a station identifier, owning operator, address, and coordinates — then call get_station_details with a station ID to pull assigned frequency bands and measured RF exposure readings for that site.
curl -X GET 'https://api.parse.bot/scraper/c2246f9e-e83d-4b0a-bd51-72510c5ee346/search_stations?max_lat=40.42&max_lon=-3.69&min_lat=40.41&min_lon=-3.70' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace geoportal-minetur-gob-es-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: query Spanish mobile telephony stations by bounding box,
drill into one station's full technical sheet, and inspect its frequencies
and exposure measurements."""
from parse_apis.geoportal_minetur_gob_es_api import Infoantenas, StationNotFound
client = Infoantenas()
# Search for stations in a bounding box over central Madrid.
for summary in client.station_summaries.search(
min_lon=-3.70, min_lat=40.41, max_lon=-3.69, max_lat=40.42, limit=5
):
print(summary.station_id, summary.operator, summary.latitude, summary.longitude)
# Drill down: take the first result and fetch its full technical sheet.
first = client.station_summaries.search(
min_lon=-3.70, min_lat=40.41, max_lon=-3.69, max_lat=40.42, limit=1
).first()
if first is not None:
station = first.details()
print(station.station_code, station.address)
# Inspect assigned frequency bands.
if station.frequencies:
for freq in station.frequencies:
print(freq.reference, freq.band_mhz, freq.band_low_mhz, freq.band_high_mhz)
# Inspect measured exposure levels around the site.
for meas in station.measurements:
print(meas.distance_m, "m", meas.azimuth_deg, "deg", meas.measured_uw_cm2, "µW/cm²")
# Point lookup by a known station identifier discovered above.
if first is not None:
try:
detail = client.stations.get(station_id=first.station_id)
print(detail.station_type, detail.operator)
except StationNotFound as e:
print("station not found:", e.station_id)
print("exercised: station_summaries.search / details / stations.get")
Lists mobile telephony base stations located inside a WGS84 bounding box (decimal degrees). One round trip. Each row is one station with its identifier, full site code, owning operator (parsed from the site code), station type, postal address, latitude and longitude. The source returns at most 1000 stations per query; when `truncated` is true the box contains more stations than were returned and the caller should split it into smaller boxes. A box with no stations is a valid empty result (count 0). There is no paging.
| Param | Type | Description |
|---|---|---|
| max_latrequired | number | Northern edge of the box, latitude in decimal degrees (WGS84); must exceed min_lat. |
| max_lonrequired | number | Eastern edge of the box, longitude in decimal degrees (WGS84); must exceed min_lon. |
| min_latrequired | number | Southern edge of the box, latitude in decimal degrees (WGS84). |
| min_lonrequired | number | Western edge of the box, longitude in decimal degrees (WGS84). |
{
"type": "object",
"fields": {
"bbox": "the queried box echoed as min_lon/min_lat/max_lon/max_lat numbers",
"count": "number of stations returned",
"stations": "array of station rows: station_id (identifier accepted by get_station_details), station_code (operator + ' - ' + station_id as published by the site), operator (owning carrier name), station_type, address, latitude, longitude",
"truncated": "true when the source's 1000-station cap was hit and the box holds more stations than returned"
},
"sample": {
"data": {
"bbox": {
"max_lat": 40.42,
"max_lon": -3.69,
"min_lat": 40.41,
"min_lon": -3.7
},
"count": 62,
"stations": [
{
"address": "CL INFANTE, 5. MADRID, MADRID",
"latitude": 40.414268,
"operator": "ORANGE ESPAGNE, S.A.U.",
"longitude": -3.699011,
"station_id": "MADR0076I",
"station_code": "ORANGE ESPAGNE, S.A.U. - MADR0076I",
"station_type": "Estación de telefonía móvil"
},
{
"address": "CL SANTA ISABEL, 15. MADRID, MADRID",
"latitude": 40.410854,
"operator": "VODAFONE ESPAÑA, S.A.U.",
"longitude": -3.697961,
"station_id": "84",
"station_code": "VODAFONE ESPAÑA, S.A.U. - 84",
"station_type": "Estación de telefonía móvil"
}
],
"truncated": false
},
"status": "success"
}
}About the Gob API
Bounding-Box Station Search
The search_stations endpoint accepts four decimal-degree coordinates (min_lat, min_lon, max_lat, max_lon) defining a WGS84 bounding box and returns every base station the source holds within that area. Each row in the stations array carries a station_id (used as the key for get_station_details), a station_code combining operator name and ID, a station_type label, a postal address, and latitude/longitude values. The count field tells you how many stations were returned, and the boolean truncated flag is set to true if the source's 1,000-station cap was hit — in that case, narrow the bounding box to guarantee full coverage.
Station Technical Detail
get_station_details accepts a single station_id (e.g. MADR0076I) exactly as emitted by search_stations, and returns the full technical sheet for that site. The frequencies array lists every assigned frequency reference: operator name, licence reference code, human-readable band_mhz text, and parsed numeric band_low_mhz / band_high_mhz edges. The measurements array holds ground-level RF exposure readings at various distances and azimuths from the mast, each row giving distance_m, azimuth_deg, and measured_uw_cm2. The measurements array may be empty if the source has no readings on file for that station.
Coverage and Identifiers
All coordinates are WGS84 decimal degrees. Station identifiers follow a structured format that encodes the owning carrier, making it straightforward to filter results by operator from the station_code field alone. The source is the Spanish Ministry of Economic Affairs (MINETUR) infoantenas registry, so coverage is Spain and its territories only. Data freshness reflects the ministry's own publication schedule.
The Gob API is a managed, monitored endpoint for geoportal.minetur.gob.es — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when geoportal.minetur.gob.es changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official geoportal.minetur.gob.es API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Map every mobile base station within a city boundary by querying a tight bounding box with
search_stations. - Audit which operators have infrastructure in a specific Spanish municipality using the
operatorfield. - Retrieve licensed frequency bands per station with
get_station_detailsto analyse spectrum allocation by carrier. - Compare measured RF exposure levels (
measured_uw_cm2) across sites at varying distances for environmental reporting. - Cross-reference
band_low_mhz/band_high_mhzvalues against national spectrum plans to identify 5G-ready installations. - Build a coverage gap analysis by correlating station density from
search_stationscounts against population data. - Verify regulatory compliance by checking whether a known mast address has exposure measurements on record.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does geoportal.minetur.gob.es offer an official developer API?+
What happens if my bounding box covers a dense urban area with many stations?+
search_stations sets truncated: true and returns only the first 1,000 rows. To retrieve all stations in a large area, split the bounding box into smaller tiles and issue separate requests until none returns truncated: true.Does the API return historical exposure measurements or signal strength predictions?+
get_station_details returns only the discrete measured exposure readings (measured_uw_cm2 at specific distance_m and azimuth_deg values) that the ministry has published for a given site. Historical time-series data and modelled propagation predictions are not part of the source record and are not returned. You can fork this API on Parse and revise it to add a custom aggregation or prediction layer on top of the raw measurements.Can I search stations by operator name or frequency band directly, without using a bounding box?+
search_stations endpoint filters only by geographic bounding box. Operator and frequency filtering must be applied client-side after retrieving results. You can fork this API on Parse and revise it to add a wrapper endpoint that accepts operator or band parameters and applies the filtering automatically.