Philippine Hazards: PAGASA Weather + PHIVOLCS Earthquakes
Pricing
from $1.00 / 1,000 earthquake records
Philippine Hazards: PAGASA Weather + PHIVOLCS Earthquakes
Structured JSON from Philippine government hazard bulletins: PAGASA daily weather, tropical cyclone status and PHIVOLCS earthquake reports.
Pricing
from $1.00 / 1,000 earthquake records
Rating
0.0
(0)
Developer
Aloever Dulay
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Philippine Hazards Actor (PAGASA + PHIVOLCS)
Structured JSON from Philippine government hazard bulletins. One run gives you the PAGASA daily weather outlook, the current tropical cyclone situation, and the latest PHIVOLCS earthquake reports, all as typed dataset items you can pipe into alerts, dashboards, models or agents.
Who needs this
- Disaster-risk and emergency teams who want machine-readable cyclone position, wind and forecast impacts instead of copying them off a web page.
- Insurers and reinsurers tracking parametric triggers (magnitude, wind speed, location) for the Philippine market.
- Logistics and shipping operators watching coastal water conditions and typhoon tracks around Luzon, Visayas and Mindanao.
- Newsrooms that need the official numbers fast, with a source URL per item.
- Researchers building time series of PHIVOLCS events or PAGASA forecasts.
- AI agents and automations that need a stable schema rather than raw HTML.
Output
The actor writes to two datasets so each record type keeps a clean, self-describing
shape (Apify dataset views can pick columns, but not filter rows, so unrelated records
belong in separate datasets). Both are documented by dataset schemas in .actor/, and the
actor's .actor/output_schema.json points integrations and AI agents at
each one:
| Dataset | Source | One item per |
|---|---|---|
default | PHIVOLCS | earthquake matching the input filters |
weather (alias) | PAGASA | run (a single nested weather snapshot) |
default dataset — earthquakes
One item per PHIVOLCS earthquake that matches the filters. Each item carries source,
type, fetchedAt (UTC, when the page was fetched) and sourceUrl, then the earthquake
fields. Timestamps from the bulletins are ISO-8601 in Manila time (+08:00).
{"source": "phivolcs","type": "earthquake","fetchedAt": "2026-09-22T22:14:52.426Z","sourceUrl": "https://earthquake.phivolcs.dost.gov.ph/","occurredAt": "2026-09-23T05:32:00+08:00","latitude": 5.56,"longitude": 125.34,"depthKm": 25,"magnitude": 1.6,"location": "018 km N 57° W of Sarangani Island (Municipality Of Sarangani) (Davao Occidental)","detailUrl": "https://earthquake.phivolcs.dost.gov.ph/2026_Earthquake_Information/September/2026_0922_2132_B1F.html"}
weather dataset — one snapshot per run
Exactly one item per run when PAGASA is selected. Provenance (source, fetchedAt,
sourceUrl) is kept once at the top level; the PAGASA parts are nested rather than
spread across many rows:
bulletin— Severe Weather Bulletin status:activeflag,headline,bulletinPdfUrland its ownsourceUrl(a different page).tropicalCyclones— every cyclone under "TC Information" (empty when none).forecasts— regional rows from "Forecast Weather Conditions".windCoastal— rows from "Forecast Wind and Coastal Water Conditions".temperatureHumidity— 24-hour temperature and humidity extremes, ornull.tidesAstronomy— Metro Manila sun/moon times and Manila Bay tides, ornull.issuedAt,synopsis— the outlook's issuance time and synopsis.
{"source": "pagasa","fetchedAt": "2026-09-22T22:14:52.024Z","sourceUrl": "https://www.pagasa.dost.gov.ph/weather","issuedAt": "2026-09-23T04:00:00+08:00","synopsis": "Trough of Tropical Depression (TD) affecting the eastern sections of Visayas and Mindanao.","bulletin": {"sourceUrl": "https://www.pagasa.dost.gov.ph/tropical-cyclone/severe-weather-bulletin","active": false,"headline": "No Active Tropical Cyclone within the Philippine Area of Responsibility","bulletinPdfUrl": null},"tropicalCyclones": [{"headline": "TROPICAL CYCLONE OUTSIDE PAR AS OF 3:00 AM TODAY","name": null,"category": "TROPICAL DEPRESSION","insidePar": false,"latitude": 14.7,"longitude": 139.5,"maxSustainedWindsKph": 55}],"forecasts": [{"place": "Eastern Visayas, Caraga, Davao Oriental, Misamis Oriental, and Camiguin","weatherCondition": "Cloudy skies with scattered rains and thunderstorms","causedBy": "Trough of TD","impacts": "Possible flash floods or landslides due to moderate to at times heavy rains"}],"temperatureHumidity": {"temperatureC": {"max": { "value": 31.9, "time": "2:00 PM" },"min": { "value": 25.7, "time": "5:00 AM" }}}}
The item shapes are defined once as zod schemas in src/schema.ts (with
the exported TypeScript types EarthquakeItem, WeatherSnapshot, ...). The committed
.actor/*_dataset_schema.json and .actor/output_schema.json are generated from those
schemas with pnpm run schemas:generate; a test fails if they drift.
Input
| Field | Type | Default | Meaning |
|---|---|---|---|
sources | string[] | ["pagasa", "phivolcs"] | Which sources to fetch. |
minMagnitude | number | 0 | Keep earthquakes with magnitude at or above this value. |
sinceHours | integer | 24 | Keep earthquakes that occurred within this many hours before the run. |
maxEarthquakes | integer | 200 | Cap on earthquake items, most recent first. |
The magnitude filter accepts fractional values through the API; the Console form
offers whole numbers because Apify input schemas only have an integer type.
Pricing
The actor uses Apify pay-per-event pricing. Users pay only for these events, never for platform usage:
| Event | Charged | Why this unit |
|---|---|---|
apify-actor-start | once per run, by Apify | Apify's synthetic start event; Apify also covers the first 5 s of compute. |
weather-snapshot | once per stored PAGASA snapshot | A weather run always yields one snapshot, so it has one price. |
earthquake-record | per stored earthquake item | Volume varies with the filters, so the user pays per record. |
Every item is charged only after it is stored, so a user never pays for data they cannot see. Before fetching a source, the actor checks that the user's spending limit covers at least one of its items and skips the source otherwise. If the limit covers only some of the earthquakes found, the actor stores and bills the most recent ones that fit. Charging is skipped entirely when the run is not billed per event (local runs, or a different pricing model), so the actor works unchanged in development.
Apify's generic per-item event, apify-default-dataset-item, is not used: each
earthquake is billed once, as earthquake-record.
Data sources and public-data basis
- PAGASA (Philippine Atmospheric, Geophysical and Astronomical Services
Administration),
https://www.pagasa.dost.gov.ph/weatherand/tropical-cyclone/severe-weather-bulletin. Official public advisories from a Department of Science and Technology agency; the site publishes no robots.txt and the pages carry no personal data. - PHIVOLCS (Philippine Institute of Volcanology and Seismology),
https://earthquake.phivolcs.dost.gov.ph/. Official public earthquake bulletins; likewise a DOST agency and no personal data.
Each run makes three requests in total (two to PAGASA, one to PHIVOLCS) with the
User-Agent ph-hazards-actor/0.1 (+https://github.com/hidden-claw/ph-hazards-actor).
Please schedule runs at a sensible cadence; the bulletins change a few times a day.
TLS note for PHIVOLCS
The PHIVOLCS server presents a valid GlobalSign certificate but does not send the
intermediate CA in the handshake, so a default Node.js client rejects it. The actor
bundles the public "GlobalSign RSA OV SSL CA 2018" intermediate
(src/certs/, with its source URL and fingerprint in the file header) and adds it to
the trust store next to Node's default roots. Certificate verification stays fully
enabled.
Limitations
- Severe Weather Bulletins are not parsed yet. When a cyclone is active PAGASA
embeds the bulletin as a PDF; the
tc_bulletin_statusitem reportsactive: trueand the PDF URL, but signal levels and the forecast track are not extracted. - PHIVOLCS lists the current month only.
sinceHourscannot reach further back than the front page shows, and detail pages are not fetched. - Cyclone summary table shape is inferred. On the capture day the multi-column table under "TC Information" was present but empty; its data rows are mapped by header name and may need adjustment once a cyclone inside PAR is observed live.
- Tide predictions cover Manila Bay only, as published by PAGASA.
Why not X
- Why not
pagasa-parser? It is Apache-2.0 and well made, but it models Severe Weather Bulletin PDFs (via@pagasa-parser/source-pdf), not the daily weather page or PHIVOLCS. It is the natural dependency for the PDF milestone above. - Why not USGS for earthquakes? USGS covers the region but with different magnitudes, locations and latency than the official Philippine bulletin, and it misses many small local events PHIVOLCS reports.
- Why not an RSS feed? Neither agency publishes a structured feed for these pages.
Development
pnpm installpnpm run buildAPIFY_LOCAL_STORAGE_DIR=$PWD/storage node dist/main.js
Put an input file at storage/key_value_stores/default/INPUT.json; earthquakes land in
storage/datasets/default/ and the weather snapshot in storage/datasets/weather/. To
exercise pay-per-event charging locally, set ACTOR_TEST_PAY_PER_EVENT=true and inspect
the charging-log dataset.
After editing src/schema.ts, run pnpm run schemas:generate to refresh the committed
dataset and output schemas in .actor/ (a test fails if they are stale).
Quality gate (also enforced by CI and the pre-commit hook):
$pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm test && pnpm run build
Tests run against saved HTML fixtures in test/fixtures/ (see the README there for
which are real captures and which are synthetic), so the suite never touches the
live sites.
License
MIT, see LICENSE.