The Earth is restless. In any given month, earthquakes rattle the planet — most too small to feel, but all carefully recorded by sensors around the globe. What if you could pull all of that data into Python and put it on a map in minutes? That is exactly what this project does.
There is something compelling about real, live data. It is one thing to practise Python with made-up lists and fictional datasets; it is another to write a handful of lines of code and get back information about actual geological events happening right now. This project is a great entry point into the world of APIs — the digital doorways that let your programs reach out to the internet and bring back structured information.
We are going to pull a month's worth of earthquake data from the US Geological Survey (USGS), load it into a Python DataFrame, and then plot it on an interactive map. No specialist hardware required — just Python and curiosity.
💡 This project was inspired by the "Fetching Current Weather Data" chapter in Automate the Boring Stuff with Python by Al Sweigart — a book well worth having on your shelf.
The full code is on GitHub: https://github.com/scottturneruon/earthquake.git
What is an API, and why does it matter here?
An Application Programming Interface (API) is a way for programs to talk to each other. In this case, the USGS provides a public API that serves up earthquake data as a JSON file — a structured text format that Python handles beautifully. You give the API a URL; it sends back data. No web scraping, no guesswork.
The USGS feed we are using covers all recorded earthquakes in the past 30 days. You can read more about the USGS and their data here: https://www.usgs.gov/about/about-us/who-we-are
What you will need
Before running the code, install the required libraries. You can drop these lines at the top of a Jupyter notebook cell and run them once:
!pip install plotly
!pip install geopandas
!pip install shapely
!pip install folium mapclassifyThese give us the tools to handle geographic data and draw maps. The main libraries in play are:
- requests — to fetch data from the USGS URL
- json — to decode the response
- pandas / json_normalize — to wrangle the nested JSON into a tidy table
- geopandas, shapely, folium — to turn coordinates into map plots
Step 1: Fetching the data
The first section sets up the URL pointing to the USGS earthquake feed and makes a request to it:
import json, requests
import pandas as pd
from pandas import json_normalize
url = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson'
response = requests.get(url)
response.raise_for_status()raise_for_status() is a useful safety net — if the request fails for any reason (no internet, server down), it will throw an error immediately rather than silently returning empty data. Good to include.
Step 2: Loading and normalising the JSON
The USGS response is formatted in JSON, but it is nested JSON — data within data within data. The json_normalize function flattens it out into a standard pandas DataFrame (see DataFrame for more details), with each earthquake as a row:
quakeData = json.loads(response.text)
df = json_normalize(quakeData['features'])Once this runs, df holds a table with columns for things like magnitude, location description, time, and — crucially — coordinates. If you add df.head() after; you can see some of the entries.
Step 3: Extracting coordinates and building a GeoDataFrame
The coordinates come back as a list of three numbers (longitude, latitude, depth). To plot them on a map, we need to split them out and convert them into geometry objects that geopandas understands:
from shapely.geometry import Point
from geopandas import GeoDataFrame
df['lon'] = pd.DataFrame(df['geometry.coordinates'].tolist())[0]
df['lat'] = pd.DataFrame(df['geometry.coordinates'].tolist())[1]
geometry = [Point(xy) for xy in zip(df.lon, df.lat)]
df = df.drop(['lon', 'lat'], axis=1)
gdf = GeoDataFrame(df, crs="EPSG:4326", geometry=geometry)The EPSG:4326 part tells geopandas we are using standard latitude/longitude coordinates (the WGS84 system used by GPS). A GeoDataFrame is essentially a pandas DataFrame with an extra superpower: it knows about shapes and geography.
Step 4: Plotting the maps
Now for the satisfying part — drawing the results. There are two approaches here.
A simple static plot — quick and clean, coloured by magnitude:
gdf.plot("properties.mag", legend=True)An interactive map using Folium — this one you can pan and zoom in a Jupyter notebook:
There is an interactive version, which you can see when you run the code (image above is a screenshot of it), it impressed me the first time I saw it — hover over any dot and you get the earthquake's details right there. It is a great reminder of just how active our planet is.
Where to go next
This project is a solid foundation, and there is plenty of room to take it further:
- Filter by magnitude — use pandas to keep only earthquakes above a certain size (e.g. magnitude 4.0+) and see how the map changes
- Add time-based analysis — the data includes timestamps; you could plot earthquakes by day of the month and look for any patterns
- Compare feeds — the USGS offers different feeds (significant earthquakes only, 4.5+, etc.). Swap the URL and see the difference instantly
- Connect it to a Raspberry Pi or micro:bit display — trigger an LED or a buzzer whenever a significant earthquake appears in the live feed. Now that would make for a genuinely interesting physical computing project
- Chart the magnitude distribution — a simple histogram with matplotlib would tell you a lot about how earthquake sizes are distributed
The full code is available at: https://github.com/scottturneruon/earthquake.git
The USGS API is free, public, and updates regularly — meaning every time you run this code, you are looking at fresh data from the real world. That, to me, is what makes projects like this worth doing.
Have you tried this project or built something similar? Drop a comment below — I'd love to see where you take it.
Comments
Post a Comment