---
title: Gempa
url: https://rone.dev/projects/gempa
description: Indonesia's earthquakes and tsunami warnings, live from BMKG, with an open JSON API.
language: en-US
updated: 2026-09-27
translations:
  id: https://rone.dev/id/projects/gempa
---

# Gempa

Indonesia's earthquakes and tsunami warnings, live from BMKG, with an open JSON API.

[Projects](https://rone.dev/projects) / [Web](https://rone.dev/projects/category/web)

Live · Started 2026 · 0 GitHub stars · 0 Forks

<Frame>
  ![The Gempa home page, with the latest felt earthquake beside a map of recent detections](https://rone.dev/projects/gempa/home.webp)
</Frame>

Gempa reads the official earthquake and tsunami feeds of BMKG, Indonesia's meteorology and geophysics agency, and serves them twice: as a fast web monitor — the latest felt earthquake, around two hundred automatic detections, tsunami bulletins, damaging earthquakes since the 1920s, and a seismicity map — and as a documented JSON API. It is unofficial; in an emergency, BMKG, BNPB and the local BPBD are the ones to follow.

## Numbers

* **13** API endpoints
* **12** Upstream feeds
* **39** Tests

## Project facts

|          |                                                                                                                                     |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| Status   | Live                                                                                                                                |
| Category | Web                                                                                                                                 |
| Started  | 2026                                                                                                                                |
| Role     | Design, build, and operations                                                                                                       |
| Stack    | Python, FastAPI, httpx, Jinja, Leaflet, Vercel                                                                                      |
| Licence  | CC0-1.0                                                                                                                             |
| Links    | [Live site](https://gempa.rone.dev) · [API reference](https://gempa.rone.dev/docs) · [Source](https://github.com/ridwaanhall/gempa) |

## Overview

BMKG publishes its earthquake data as files: an XML feed of the latest detections, JSON catalogues, GeoJSON fault lines, shakemap images and press narratives. They are published for BMKG's own clients, and they arrive in several formats with several conventions for the same thing.

Gempa sits in front of them. The web interface has a page for each question a reader actually has — what just happened, what is being detected right now, which earthquakes were felt, which were strong, whether there is a tsunami warning, which ones did damage, and where it all sits on a map. Every page is rendered on the server, so it is readable and indexable before any script runs, and then refreshes itself from the API.

## Twelve feeds, one shape

The API normalises everything it serves. Keys are English, numbers are numbers rather than strings with units attached, coordinates are signed decimal degrees instead of "8,10° LS", and every time carries an explicit offset. Lists come back as `data` and `meta` — count, source, and when the response was generated — whichever of the twelve upstream feeds they were read from.

A realtime detection is not final: BMKG revises its magnitude and location as more stations report. Gempa serves each event's revision history alongside it, so a caller can see how a reading moved instead of only its latest value.

## The upstream stays on the server

The address of BMKG's feed bucket is configuration, read from the environment and used server-side only. Every feed, every shakemap and every narrative is fetched by the server and re-served under `/api/v1`, so the browser never learns where the data comes from, and an upstream error reaches the reader as a generic message rather than a URL.

The press narratives are HTML written by someone else, which makes them the one part of the upstream that could carry markup into the page. They are passed through nh3 against an allow-list of paragraph, list, table and emphasis tags before they are served.

## Two caches, and stale over broken

Each response carries a CDN lifetime matched to its feed: thirty seconds for realtime detections, a minute for felt earthquakes and tsunami bulletins, a day for stations and fault lines. Behind the CDN, an in-process cache holds each feed for the same window, with a lock per key, so a burst of requests for the same feed becomes one upstream call.

When BMKG cannot be reached, that cache serves its last good answer for up to an hour rather than an error. For a service people open during an earthquake, the latest answer from a few minutes ago is more useful than a failure.

## Tested without the network

The thirty-nine tests run against recorded copies of the real feeds, with the upstream mocked, so the parsers are checked against the formats BMKG actually publishes and the suite passes offline. The pages send a Content Security Policy under which the only inline script is the import map, admitted by its hash.

<Frame>
  ![The Gempa seismicity map, with realtime detections over Indonesian fault lines](https://rone.dev/projects/gempa/map.webp)
</Frame>

<CardGroup cols={2}>
  <Card title="Previous: Sivitas API" href="https://rone.dev/projects/sivitas-api">
    Indonesian higher-education records — universities, programmes, lecturers, students.
  </Card>

  <Card title="Next: igstats" href="https://rone.dev/projects/igstats">
    Upload your own Instagram export and see who does not follow you back.
  </Card>
</CardGroup>
