Event and station data from the GeoShake community earthquake early-warning network — free to use for research, education and applications.
curl https://api.geoshake.org/api/events [ { "event_id": 7, "originMs": 1783678236932, "lat": 36.57, "lon": 31.06, "nStations": 3, "intensityClass": "orta", "maxPga": 0.106 }, … ]
All GeoShake event and station data is published under Creative Commons Attribution 4.0 (CC BY 4.0). You may use, share and adapt it — including in academic publications and commercial products — as long as you credit GeoShake. The full terms, including the station-privacy and no-warranty notes, are in data/LICENSE.
GeoShake is a community monitoring network, not an official earthquake early warning service. Don't use it as the sole basis for life-safety, evacuation or emergency-response decisions — follow your national seismological and civil protection authorities.
Start anonymous, add a free API key for the historical catalog, or request a personal real-time feed.
One free GeoShake account works everywhere: this API, the Home Assistant integration and Google Home linking. Log in to mint your personal key — copy it, or regenerate at any time.
New here? Create a GeoShake account in the mobile app, then log in to get your API key.
Public read endpoints under api.geoshake.org — great for prototyping and live dashboards.
Sign up is free — a key is issued against your GeoShake account so we can apply fair-use quotas and keep researchers informed of changes.
Use the panel above — or the API directly. Logging in returns your existing key; pass "regenerate": true to force a new one (the old key becomes invalid).
curl -X POST https://api.geoshake.org/api/data/key \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"..."}'Pull events by date range in JSON or CSV.
curl "https://api.geoshake.org/api/data/events?from=2026-01-01T00:00:00Z&to=2026-07-01T00:00:00Z&format=csv" \ -H "X-API-Key: YOUR_KEY" -o geoshake-events.csv
license and citation fields, plus truncated: true when the row limit was hit — narrow the date range and continue.After an earthquake, GeoShake app users can report how strongly they felt it. Those reports are aggregated into ~300 m cells and published per event as a plain GeoJSON FeatureCollection on the Modified Mercalli (MMI) scale — QGIS, Leaflet, GDAL/ogr2ogr and geopandas read it as-is. Two endpoints, in this order: /api/intensity lists the events that have data, then /api/intensity/{eventKey} returns the cells for one of them.
This is a human-reported layer: what people say they felt, not what an instrument measured. Keep it apart from the PGA and intensityClass fields of the endpoints above, and from the phone-accelerometer layer on the map — those are machine measurements. No API key is needed here, so the access tiers and the key panel above don't apply to this endpoint.
One keyless GET lists every earthquake that has published felt-report data, newest first. Each entry hands you the eventKey for step 2 together with a catalog summary and the counts — you don't build keys, and you don't probe events to find out which ones are worth asking about.
curl "https://api.geoshake.org/api/intensity" # Optional paging — newest first, 1-200 per page curl "https://api.geoshake.org/api/intensity?limit=100&offset=0"
limit/offset is 400; if the service itself is down you get 503, never a fake empty list. Cached ~60 s.eventKey, and put the other agencies' keys in mergedKeys so you can match this entry against your own catalogue without de-duplicating the list yourself. Aftershocks are not merged — a separate quake minutes later stays a separate entry.Take an eventKey from step 1 and GET it — again no headers. Each feature is one published cell; the collection also carries the event, the counting window and the licence in metadata.
curl "https://api.geoshake.org/api/intensity/eq_USGS_us6000tjl2" # Plain GeoJSON — save it and open it in QGIS, ogr2ogr, Leaflet, geopandas… curl -s "https://api.geoshake.org/api/intensity/eq_USGS_us6000tjl2" -o felt-reports.geojson
features array. Cached ~30 s while the report window is open, ~5 min once it has closed. Both intensity endpoints are anonymous and rate-limited per IP: over the limit you get 429, never a fake empty collection.metadata.event.source can name an agency you did not ask for. That is the merge working, not a mismatch: eventKey always echoes what you asked for, canonicalKey names the group's chosen record, and mergedKeys lists the rest. Reports are counted once per person, so a merged event never double-counts.eq_<source>_<sourceEventId> — USGS event us6000tjl2 becomes eq_USGS_us6000tjl2, sources being the agencies GeoShake mirrors (USGS, EMSC, AFAD). A single catalog record at /api/quakes/{id} carries both source and source_event_id; the list endpoint /api/quakes does not, which is exactly why step 1 exists. Records without an agency id use the fallback form eqid_<id>, built from that record's numeric catalog id.Reports are counted inside the window the response states — windowStart → windowEnd, closing 60 minutes after origin time. Once that window is closed the result stops changing.
intensityClass, or with the phone-accelerometer layer. A cell is published only after at least 3 independent reports; a single report is never released. That is also why a feature is a ~300 m polygon and not a point: lat/lon is the cell centre, deliberately not a reporter's position, and reportCount sums published cells only. An empty features array is the normal outcome for most events — a 200 with nothing to draw, not a failure. And none of this is an official damage assessment: for that, follow your national seismological and civil-protection authority.license and attribution inside metadata so a pipeline can pick them up automatically.For live pipelines, request personal read-only MQTT credentials with your account and subscribe to the events topic over TLS (port 8883).
geoshake/events · TLS :8883
Returns { broker, port, username, password } — works with any MQTT client: paho, aiomqtt, mosquitto_sub.
curl -X POST https://api.geoshake.org/api/ha/credentials \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"..."}'
# → { broker, port, username, password }
# → subscribe with paho / aiomqtt / mosquitto_subBeyond the confirmed catalog, GeoShake streams live waveform data over the seismology community's standard SeedLink protocol. Point ObsPy, jAmaSeis, SWARM — or any SeedLink client — at seedlink.geoshake.org:18000 and watch stations in real time.
Network GW. Four channels per station: LNZ (1 Hz gravity-referenced vertical envelope — absolute value, no polarity), ENZ (~110 Hz event bursts, gravity-referenced vertical) and EN1/EN2 (~110 Hz event bursts, the two horizontals — azimuth not published). Station codes match the station pages (e.g. BH2JN).
from obspy.clients.seedlink.easyseedlink import create_client
def on_data(trace):
print(trace.id, trace.stats.starttime, len(trace.data), "samples")
client = create_client("seedlink.geoshake.org:18000", on_data)
client.select_stream("GW", "BH2JN", "LNZ") # 1 Hz GRAVITY-REFERENCED VERTICAL envelope (|z| peak, no polarity)
# client.select_stream("GW", "BH2JN", "ENZ") # ~110 Hz bursts, GRAVITY-REFERENCED VERTICAL
# client.select_stream("GW", "BH2JN", "EN1") # ~110 Hz bursts, horizontal, azimuth NOT published
# client.select_stream("GW", "BH2JN", "EN2") # ~110 Hz bursts, horizontal, perpendicular to EN1
client.run()LNZ is the 1 Hz envelope of gravity-referenced vertical acceleration: each sample is the per-second peak of the absolute value of the vertical component, obtained on the device by projecting every raw sample onto the gravity direction estimated from that same second (the window-mean acceleration, no long-term filter), so a wall-mounted unit and a flat unit give the same definition. The axis is an estimate, not a levelled one: asymmetric shaking inside a window tilts the window mean and the projection axis with it, in proportion to shaking amplitude over g. It is an envelope, not a waveform: non-negative, no polarity, no phase, so the trace never crosses zero; do not rotate it with the horizontals and do not treat it as a signed component. Samples archived before 10 September 2026 were the three-axis vector magnitude instead (see the HISTORY comment in StationXML). ENZ is a signed single component (~110 Hz, gappy — triggers only) and it is gravity-referenced vertical: since 5 August 2026 the burst samples are rotated into a local frame established from gravity before they are published, so StationXML reports Azimuth 0, Dip -90 (positive up). EN1 and EN2 are the two horizontals, orthogonal to ENZ and to each other, right-handed with up: their Dip is 0 and their Azimuth is deliberately absent — the devices carry no magnetometer, so gravity gives us "down" but not "north". SEED reserves the N/E component letters for true north and east, which is why they carry 1/2 instead; if you need geographic horizontals, they are not in this data. All four are uncalibrated — the published response is a nominal datasheet sensitivity (counts = m/s² × 10⁶), not a per-unit calibration. Provisional: the codes are kept to avoid breaking live clients — an earlier version of this page said true three-component data was planned and that these codes would change meaning when it shipped; it shipped on 5 August 2026 and the codes did not change. Anchor your processing to the StationXML <Description>, not the code.For education, connect the free IRIS app jAmaSeis and let students watch quakes arrive live and pick P/S phases. In jAmaSeis: File → Manage Sources → Add Source: Raspberry Shake, enter seedlink.geoshake.org:18000, hit Get Stations, then add a GW_…_LNZ (activity) or …_ENZ (events) channel.
GeoShake speaks the seismology community's own standards — anonymous FDSN web services returning QuakeML and StationXML. Point ObsPy at api.geoshake.org and pull events and station metadata the same way you would from IRIS or a national network.
fdsnws-event serves the confirmed catalog as QuakeML 1.2; fdsnws-station serves network/station metadata as StationXML 1.1. Both are anonymous and rate-limited per IP.
from obspy import UTCDateTime
from obspy.clients.fdsn import Client
# GeoShake speaks the standard FDSN web services (no authentication).
client = Client(base_url="https://api.geoshake.org")
# Event catalog -> QuakeML (magnitude = PGA-derived MMI, NOT a seismic magnitude)
cat = client.get_events(starttime=UTCDateTime("2026-01-01"),
minmagnitude=2.0) # MMI threshold
print(cat) # ObsPy Catalog object
# Station metadata -> StationXML (network "GW", FDSN-registered, uncalibrated)
inv = client.get_stations(network="GW", level="channel")
print(inv)
# What the samples REALLY are - read this before processing. LNZ is the 1 Hz
# ENVELOPE of gravity-referenced vertical acceleration (per-second peak |value|, no
# polarity - since 2026-09-10; earlier archive = vector magnitude, see the
# channel HISTORY comment). ENZ/EN1/EN2 are genuine signed components: ENZ is
# gravity-referenced vertical (Azimuth 0, Dip -90); EN1/EN2 are the horizontals and their
# azimuth is NOT published, because the devices carry no magnetometer.
print(inv[0][0][0].description)magnitude is a PGA-derived Modified Mercalli Intensity (MMI), explicitly labelled not a seismic magnitude — GeoShake computes neither ML/Mw nor depth. Network GW is a permanent, FDSN-registered code, but the sensors are uncalibrated MEMS: StationXML serves level=channel, where each channel states in its <Description> what the samples actually are, but level=response serves a nominal instrument sensitivity (counts = m/s² × 10⁶, derived from the sensor datasheet). It is not a per-unit calibration and carries no poles/zeros model. There are four channels per station — LNZ, ENZ, EN1, EN2 — and StationXML publishes Azimuth/Dip only where they are known: ENZ carries Azimuth 0, Dip -90 because gravity gives us the vertical axis; the two horizontals carry Dip 0 with no Azimuth, because without a magnetometer we know they are orthogonal but not which way they point; LNZ also carries Azimuth 0, Dip -90 — the measured axis is the vertical, even though the samples are absolute values. An absent field there means unknown, not forgotten — each channel carries a comment saying which case it is.For reproducible research, catalog snapshots are archived on Zenodo under CC-BY-4.0 with a citable DOI. Cite the concept DOI below — it is version-stable and always resolves to the latest snapshot.
GeoShake Community Seismic Network (2026). GeoShake Community Seismic Event Catalog. Zenodo. https://doi.org/10.5281/zenodo.21313786
The Zenodo DOI above identifies a snapshot of the event catalog. The network — the stations, their metadata and the waveforms — is a separate object with its own permanent identifier: GW is registered with the FDSN as GeoShake Global Seismic Network (the registry entry is public), with DOI 10.7914/ft1b-4x43. Since 6 September 2026 GeoShake is also listed in the FDSN data centre registry as GEOSHAKE, with three services declared there: fdsnws-station, fdsnws-event and SeedLink. If your work uses GeoShake waveforms or station metadata, cite the network:
GeoShake (2026): GeoShake Global Seismic Network. International Federation of Digital Seismograph Networks. Dataset/Seismic Network. https://doi.org/10.7914/ft1b-4x43
<Identifier type="DOI"> on the StationXML <Network> element.3+ GeoShake stations must agree before an event is published — a conservative catalog with a low false-alarm rate.
Waveform snippets are stored around trigger windows only. GeoShake does not archive continuous waveforms. A null inside samples is a missing sample (gap) — it is not a zero reading; do not plot it as 0.
Classes hafif · orta · şiddetli are network-derived shaking categories. max_pga is the highest measured peak ground acceleration across triggering stations, taken from the 1 Hz feature stream at the moment the event was solved. It is a three-component vector magnitude (not the max-horizontal convention used by most GMPEs; measured ratio 1.03–1.16×). If a station's measurement had not arrived yet, its trigger-onset amplitude is used instead, so the value is a lower bound. Before 2026-09-20 this field carried the trigger-onset amplitude, which under-reads the true peak by a median factor of 2.94 (measured, n=14); historical rows have been recomputed. This set is not closed — we may add a class later, so treat an unfamiliar intensityClass as a display value rather than an error.
A community network — data quality varies with station density. It complements national networks (AFAD/Kandilli, USGS…), it doesn't replace them.
Stations are consumer-grade MEMS accelerometers. They are not calibrated: the response served at level=response is a nominal datasheet sensitivity, not a per-unit calibration — no shake-table calibration, no coupling or mounting correction, no poles/zeros model. Amplitudes are indicative, not metrologically traceable.
Station elevation is sampled from a digital elevation model (DEM) at the reported coordinates. It is not a survey, and it describes the terrain rather than the sensor — a unit on an upper floor of a building sits above the published figure. Where elevation is unknown the StationXML schema still requires the field, so 0 is published and the station comment says it means "unknown", not sea level. Depth stays 0: the sensor's height above the local ground surface is not recorded.
The code GW in StationXML, SAC and SeedLink is permanent and registered with the FDSN — since 27 August 2026, as GeoShake Global Seismic Network, DOI 10.7914/ft1b-4x43; the FDSN registry entry is public. It will not change, so you can safely rely on it.
Holding GeoShake files from before 27 Jul 2026? They carry GS, which was a mistake on our part — the FDSN has GS assigned to a USGS network. Don't merge those files into a shared archive under GS; re-fetch and they will carry GW.
Anonymous fdsnws-event & fdsnws-station serving QuakeML and StationXML — ObsPy works out of the box today.
The catalog is published on Zenodo under CC-BY-4.0 with a citable DOI — 10.5281/zenodo.21313786. See how to cite.
Real-time activity envelopes + event bursts over SeedLink — open in ObsPy, jAmaSeis or SWARM at seedlink.geoshake.org:18000.
Downloadable trigger-window snippets in miniSEED alongside the event catalog for signal-level analysis (live SAC per-trigger already available on station pages).