What earthquakes does USGS record around the world, and how can I explore those near Peru? That question led to Global Earthquake Monitoring Dashboard, a Python project built with Streamlit and Plotly.
The app retrieves real earthquake records and lets users explore them through an interactive map, date and magnitude filters, regional views, charts, and CSV exports.
Explore the source code on GitHub
This is an educational data exploration tool. It does not predict earthquakes or issue emergency alerts. USGS records can be revised.
What the dashboard includes
- An interactive world map with zoom and event details.
- Filters for UTC dates, magnitude, and region: worldwide, Peru and surrounding areas, or South America.
- KPIs for event count, maximum magnitude, events with magnitude ≥ 5, and median depth.
- Daily counts, a magnitude histogram, and a magnitude-versus-depth scatter plot.
- A ranking of the ten largest events and a table of all returned records.
- CSV downloads of the selected dataset.
The app interface and README are currently in Spanish, with a focus on Peru and South America. This walkthrough explains the implementation in English.
Separating data access from the interface
The project has two main components. earthquake/data.py validates queries and converts GeoJSON into a pandas DataFrame. app.py handles the filters, caching, visualizations, and download button.
Form → Validated query → USGS → Normalization → Cache → Map / KPIs / Charts / CSV
This separation makes it possible to test data processing without opening a browser or depending on USGS availability.
Querying real earthquake data
The app uses the USGS Earthquake Catalog API with GeoJSON output and eventtype=earthquake to exclude other event types.
Each query includes UTC dates and magnitude limits. Regional views add geographic bounding boxes:
| Region | Latitude | Longitude |
|---|---|---|
| Peru and surrounding areas | −20 to 1 | −85 to −68 |
| South America | −60 to 15 | −90 to −30 |
These rectangles include offshore areas and neighboring countries. They are not political boundaries, so the Peru view should not be interpreted as a dataset containing only earthquakes inside Peru.
USGS recommends its GeoJSON feeds for real-time displays whenever possible. I chose the catalog service because this project supports custom historical date ranges. The dashboard queries data on demand; it does not maintain a live stream.
Making the final date inclusive
A date such as 2024-01-02 can represent the beginning of that day. Using it directly as an end time could exclude events occurring after midnight.
The app converts the final day to 23:59:59.999999 UTC. It also displays when the data was retrieved, separately from the event timestamps. An earthquake's origin time and the time of the API request answer different questions.
Mapping magnitude and depth
The map uses Plotly with OpenStreetMap tiles. Marker size helps compare magnitudes, while color represents depth.
Marker size is not an energy scale, and depth color is not a risk rating. Magnitude and intensity are different measurements, and the catalog can contain different magnitude types.
The charts add context to the map. Daily counts include days with zero events, the histogram shows the magnitude distribution, and the scatter plot helps explore depth and magnitude together. Every KPI describes only the records returned for the current selection.
Handling failures and incomplete records
An external API can respond slowly, return incomplete data, or become unavailable. The app includes:
- A five-second connection timeout and a thirty-second read timeout.
- Limited retries for transient failures, including HTTP 429 and selected 5xx responses.
- Explicit messages for empty results and service errors.
- A ten-minute cache and a button to force a refresh.
- Validation of event IDs, timestamps, and coordinates, plus deduplication by ID.
Missing magnitudes and depths remain null rather than becoming zero. Records without usable coordinates, timestamps, or identifiers are skipped, and the app reports how many were omitted.
USGS limits queries to 20,000 events. If a response reaches that size, the dashboard asks the user to narrow the date range or increase the minimum magnitude. It does not present a potentially truncated result as a complete dataset. Automatic pagination is a future improvement.
The CSV export also neutralizes text fields that spreadsheet software might interpret as formulas.
Testing the pipeline and the app
The project includes 18 automated tests covering inclusive dates, regions, null values, duplicates, timeouts, HTTP errors, empty responses, and the event limit. Interface tests use Streamlit AppTest with controlled responses.
Local checks passed. GitHub Actions also completed Ruff and pytest successfully on Python 3.11 and 3.12 for implementation commit 90f9d34.
I also checked a real USGS query: January 1–7, 2024, UTC, magnitudes 4–10, in the Peru and surrounding areas bounding box. It returned 8 events, with no omitted records and a maximum magnitude of 5.3. These figures describe that specific query, not earthquake activity across Peru in general.
Controlled tests verify behavior even when USGS is unavailable. The real request separately checks the HTTP integration and normalization.
Running it locally
With Python 3.11 or 3.12 installed:
git clone https://github.com/Cristhian465/global-earthquake-monitoring-dashboard.git
cd global-earthquake-monitoring-dashboard
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
streamlit run app.py
On Windows PowerShell, activate the environment with:
.venv\Scripts\Activate.ps1
To run the quality checks and tests:
python -m pip install -r requirements-dev.txt
ruff check .
pytest -q
Preparing for Streamlit Community Cloud
The repository includes requirements.txt and Streamlit configuration. The entry point is app.py, and no API keys are required.
The README explains how to select the repository, the main branch, and Python 3.12 in Community Cloud. At the time of writing, the app has not been deployed. You can run it locally using the steps above.
Reference: Streamlit's deployment guide.
What I would improve next
Two useful additions would be administrative boundaries for country-specific analysis and split queries for longer historical periods. Comparing catalogs and documenting coverage differences would also help: fewer small recorded events in a region do not necessarily mean less seismic activity.
Building this project brought together API integration, interactive visualization, and decisions that affect interpretation: date boundaries, missing values, query limits, and geographic coverage.
The code is available under the MIT license on GitHub, together with tests and setup instructions. Earthquake data is attributed to USGS, and the map to © OpenStreetMap contributors.
Which feature would you add first: country filters using exact boundaries, or support for longer historical periods?
Top comments (0)