# USGS Earthquake Data Scraper — FDSN Event Feed (`devilscrapes/usgs-earthquake-data-scraper`) Actor

Query the USGS FDSN earthquake catalog by time window, magnitude, depth, bounding box, or radius and get one flat row per event — magnitude, location, depth, significance, alert level, tsunami flag, and felt reports, ready for JSON, CSV, or Excel export.

- **URL**: https://apify.com/devilscrapes/usgs-earthquake-data-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Developer tools, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

<p align="center">
  <img src=".actor/icon.svg" width="160" alt="USGS Earthquake Data Scraper — Devil Scrapes">
</p>

## USGS Earthquake Data Scraper — FDSN Event Feed

**$0.05 per run + $0.002 per earthquake event — about $2.05 per 1,000
events.** Pay only for results that land, no credit card required to try.

USGS's earthquake catalog is the world's authoritative seismic-event
record, but its FDSN event web service answers in raw, deeply nested
GeoJSON — every buyer ends up writing the same coordinate-unpacking,
epoch-to-ISO, and pagination code from scratch. We already wrote it. Point
this Actor at a time window and any combination of magnitude, depth,
bounding-box, or radius filters, and get back one flat row per event —
ready for a spreadsheet, a dashboard, or a database import.

### 🌍 What this scrapes

USGS's public **FDSN event web service**
(`earthquake.usgs.gov/fdsnws/event/1/query`) — the same catalog that feeds
USGS's own earthquake map. Every event in scope carries magnitude, exact
location, depth, significance score, PAGER alert level, tsunami flag, and
community felt-report data (CDI/MMI), flattened into one typed row.

### 🔥 Features

- **Full FDSN parameter surface** — magnitude, depth, and time filters,
  **plus both bounding-box and radius search** — most rival scrapers only
  cover a magnitude-and-date box.
- **Every risk field on every row** — `alert`, `tsunami`, `sig`, `felt`,
  `cdi`, and `mmi` are first-class output columns, not buried in nested
  JSON you have to dig for.
- **Flat, typed output** — a fixed schema (`event_id`, `magnitude`,
  `place`, coordinates, depth, and 14 more), not raw GeoJSON re-wrapped.
- 🛡️ **We rotate browser fingerprints** (curl-cffi impersonation across
  Chrome, Firefox, and Safari profiles) on every request.
- 🔁 **We retry with exponential backoff** on `408/429/5xx` and honour
  `Retry-After`, up to 5 attempts per page — a busy USGS endpoint never
  costs you a failed run.
- 🧱 **We never crash on a bad record.** A malformed event is skipped with
  a logged warning; every other event in your search still lands in the
  dataset.
- 🧊 **A zero-match search still succeeds.** A narrow filter combination
  that matches nothing finishes with a clear status message, not a
  failed run and a wasted charge.

### 💡 Use cases

- **Catastrophe-risk and reinsurance monitoring** — pull every event above
  a magnitude threshold in a region and feed it straight into an exposure
  model.
- **Geotech and infrastructure risk dashboards** — track seismic activity
  near a specific site with a radius search centered on the asset.
- **News-desk earthquake alerting** — poll a rolling time window and
  surface new events with their alert level and felt-report counts.
- **Research and academic datasets** — build a clean, reproducible seismic
  event table without hand-parsing GeoJSON.

### ⚙️ How to use it

1. Set a time window with `starttime` and `endtime` (accepts
   `YYYY-MM-DD` or full ISO-8601).
2. Optionally add a magnitude, depth, bounding-box, or radius filter.
3. Run the Actor — the dataset fills with one row per matching event.
4. Export as JSON, CSV, or Excel straight from the Console, or pull it
   via the API.

No API key. No account. Just a time window and, optionally, a filter.

### 📥 Input

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `starttime` | string | yes | — | Earliest event time (inclusive). |
| `endtime` | string | yes | — | Latest event time (inclusive). |
| `minmagnitude` | number | no | — | Only events at or above this magnitude. |
| `maxmagnitude` | number | no | — | Only events at or below this magnitude. |
| `mindepth` / `maxdepth` | number | no | — | Depth filter, in kilometers. |
| `minlatitude`/`maxlatitude`/`minlongitude`/`maxlongitude` | number | no | — | Bounding-box filter — all four together or none. |
| `latitude`/`longitude`/`maxradiuskm` | number | no | — | Radius-search center and extent — all three together or none. |
| `orderby` | select | no | `time` | Sort order: `time`, `time-asc`, `magnitude`, `magnitude-asc`. |
| `limit` | integer | no | `500` | Events requested per FDSN page (USGS hard-caps at 20 000). |
| `max_items` | integer | no | `2000` | Stop after this many events. `0` = unlimited (paginate until a short page). |
| `proxyConfiguration` | object | no | Apify Proxy on | Proxy settings — Apify Proxy is enabled by default. |

Example input:

```json
{
  "starttime": "2026-08-03",
  "endtime": "2026-09-02",
  "minmagnitude": 4.5
}
```

### 📤 Output

One row per earthquake event:

```json
{
  "event_id": "us7000td6k",
  "magnitude": 4.8,
  "magnitude_type": "mb",
  "place": "176 km SE of Gizo, Solomon Islands",
  "event_time": "2026-08-30T02:00:29.055Z",
  "updated_time": "2026-08-30T02:28:22.040Z",
  "longitude": 158.1558,
  "latitude": -9.0154,
  "depth_km": 10.0,
  "alert_level": null,
  "tsunami": false,
  "significance": 354,
  "felt_reports": null,
  "cdi": null,
  "mmi": null,
  "status": "reviewed",
  "event_type": "earthquake",
  "title": "M 4.8 - 176 km SE of Gizo, Solomon Islands",
  "event_url": "https://earthquake.usgs.gov/earthquakes/eventpage/us7000td6k",
  "network": "us"
}
```

Optional USGS fields (`magnitude`, `felt_reports`, `cdi`, `mmi`, `alert_level`,
and more) come back as `null` when USGS itself doesn't report them for a
given event — never a missing key, never a crashed row.

### 💰 Pricing

This Actor bills **Pay-Per-Event**, so the invoice matches what you
actually received:

| Event | Price |
|---|---|
| Actor start | **$0.05** per run |
| Result emitted | **$0.002** per earthquake event written to the dataset |

That works out to roughly **$2.05 per 1,000 events**. A run that finds
nothing costs you the start fee and nothing else — no data, no per-row
charge.

### 🚧 Limitations

- USGS's FDSN endpoint caps a single page at 20 000 events and this Actor
  respects that ceiling — extremely wide time windows may need to be
  split into smaller searches.
- The `/count` pre-flight endpoint and the per-event detail endpoint
  (`eventid=`) are out of scope for this version; every field the detail
  endpoint would add for the list view is already on each row.
- `eventtype`, `catalog`, `contributor`, and a handful of other long-tail
  FDSN parameters aren't exposed yet — open a feature request if you need
  one.

### ❓ FAQ

**Do I need a USGS API key?** No — the FDSN event web service is public
and keyless. You don't need an account either.

**What happens if my search matches nothing?** The run finishes
successfully with zero rows and a status message describing exactly what
was searched — you're never charged a per-row fee for zero rows, and the
run never fails just because a narrow filter combination matched
nothing.

**Can I search by location without a bounding box?** Yes — use the
radius-search fields (`latitude`, `longitude`, `maxradiuskm`) to center a
search on a point instead of drawing a box.

**Why did my run fail instead of just returning nothing?** A run fails
loud only when USGS itself rejects the request (a malformed parameter
value, for example) or is unreachable after retries — that's a real
error, not an empty result, and we never disguise the difference.

**Can I combine a bounding box and a radius search in the same run?**
No — USGS treats them as alternative location filters, so set one or the
other, not both, in a single run.

### 🙌 Your feedback

Found an issue or have a feature request for the USGS Earthquake Data
Scraper? Reach out via
<https://apify.com/DevilScrapes> — we read
every message and ship fixes fast.

# Actor input Schema

## `starttime` (type: `string`):

Earliest event time (inclusive). Accepts <code>YYYY-MM-DD</code> or full ISO-8601, passed through to USGS unchanged.

## `endtime` (type: `string`):

Latest event time (inclusive). Accepts <code>YYYY-MM-DD</code> or full ISO-8601, passed through to USGS unchanged.

## `minmagnitude` (type: `number`):

Only events at or above this magnitude.

## `maxmagnitude` (type: `number`):

Only events at or below this magnitude.

## `mindepth` (type: `number`):

Only events at or below this depth in kilometers (deeper = larger value).

## `maxdepth` (type: `number`):

Only events at or above this depth in kilometers.

## `minlatitude` (type: `number`):

Bounding-box filter. Must be set together with Max latitude, Min longitude, and Max longitude — all four or none.

## `maxlatitude` (type: `number`):

Bounding-box filter. Must be set together with Min latitude, Min longitude, and Max longitude — all four or none.

## `minlongitude` (type: `number`):

Bounding-box filter. Must be set together with Min latitude, Max latitude, and Max longitude — all four or none.

## `maxlongitude` (type: `number`):

Bounding-box filter. Must be set together with Min latitude, Max latitude, and Min longitude — all four or none.

## `latitude` (type: `number`):

Radius-search center. Must be set together with Center longitude and Max radius (km) — all three or none.

## `longitude` (type: `number`):

Radius-search center. Must be set together with Center latitude and Max radius (km) — all three or none.

## `maxradiuskm` (type: `number`):

Radius-search extent in kilometers. Must be set together with Center latitude and Center longitude — all three or none.

## `orderby` (type: `string`):

Sort order for returned events.

## `limit` (type: `integer`):

Events requested per FDSN page. USGS hard-caps this at 20 000.

## `max_items` (type: `integer`):

Stop after this many events. Each row is one billed result. Set to 0 for unlimited (paginate until a short page).

## `proxy_configuration` (type: `object`):

USGS is a public keyless API. Apify Proxy is enabled by default per repo convention.

## Actor input object example

```json
{
  "starttime": "2026-08-03",
  "endtime": "2028-01-01",
  "minmagnitude": 4.5,
  "orderby": "time",
  "limit": 500,
  "max_items": 2000,
  "proxy_configuration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "starttime": "2026-08-03",
    "endtime": "2028-01-01",
    "minmagnitude": 4.5,
    "orderby": "time",
    "limit": 500,
    "max_items": 2000,
    "proxy_configuration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/usgs-earthquake-data-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "starttime": "2026-08-03",
    "endtime": "2028-01-01",
    "minmagnitude": 4.5,
    "orderby": "time",
    "limit": 500,
    "max_items": 2000,
    "proxy_configuration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/usgs-earthquake-data-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "starttime": "2026-08-03",
  "endtime": "2028-01-01",
  "minmagnitude": 4.5,
  "orderby": "time",
  "limit": 500,
  "max_items": 2000,
  "proxy_configuration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/usgs-earthquake-data-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devilscrapes/usgs-earthquake-data-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Frqrhre7AM5eyCRQ7/builds/vYixhKWX34RlLPCsm/openapi.json
