GDELT Events
Geopolitical and economic events extracted from worldwide news by the GDELT project, coded by actor, action and location.
gdelt_events — the dataset name to pass to the Obscura API.
What one row means
One CAMEO-coded actor-action-actor event that GDELT 2.0's NLP pipeline extracted from world news coverage and published in a single 15-minute Event-table export slot, keyed on GDELT's own globally unique GlobalEventID (one physical event can still spawn several GlobalEventIDs across different articles/slots — this table does not dedupe across those).
One row per global_event_id — GDELT's own globally unique event identifier (F1), unique across the entire v2 history and across every 15-minute export slot..
Point-in-time availability
Every Obscura dataset carries available_date: the calendar day the publisher made the row
available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the
same thing on every dataset in the catalog.
For gdelt_events: available_date = date_added (F60), the 15-minute export-slot stamp under which this row's export.CSV.zip was published to data.gdeltproject.org — the collector builds the download URL directly from this same stamp, so it is provably the moment the row became publicly fetchable.
Refresh cadence
Obscura refreshes gdelt_events weekly — the most frequent scheduled job that re-collects or re-exports it. This is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when a row became public is recorded per row in available_date.
Schema — 36 columns
The full public column list for gdelt_events, with the meaning of every field. The same
schema is served unauthenticated at https://api.obscura.trade/v1/catalog/gdelt_events.
| Column | Type | Description |
|---|---|---|
| global_event_id | bigint · not null | GDELT GlobalEventID (F1) — a globally unique, monotonically-assigned ID stamped by GDELT itself at extraction time; the primary key and the ON CONFLICT target for the upsert in gdelt.rs::conflict(). |
| occurred_on | date · not null | Parsed from SQLDATE (F2, YYYYMMDD) — GDELT's NLP-inferred date of the real-world event itself; a period/event date, distinct from available_date (when the row became public). |
| actor1_code | text | Actor1 CAMEO code (F6) — a compact code (country/ethnic/religious/type qualifiers concatenated) identifying the first, typically initiating, actor in the event; e.g. 'USA', 'CHN', 'COP' (police). Empty source cells become NULL via nonempty(). |
| actor1_name | text | Human-readable name for Actor1 (F7), e.g. 'UNITED STATES', 'CHINA'; the display counterpart to actor1_code, extracted from the same CAMEO actor block. |
| actor1_country_code | text | Actor1CountryCode (F8) — 3-char CAMEO country code of Actor1's NATIONALITY (e.g. 'USA', 'CHN'), distinct from where the action occurred (action_geo_country); empty source cells become NULL. |
| actor1_type1_code | text | Actor1Type1Code (F13) — Actor1's primary CAMEO role/type category (GOV, MIL, BUS, COP, MED, REB, …); the categorical actor-kind filter. |
| actor2_code | text | Actor2 CAMEO code (F16) — the second/target actor in the coded interaction, same coding scheme as actor1_code; NULL when the event has only one actor (e.g. a natural disaster with no counterpart). |
| actor2_name | text | Human-readable name for Actor2 (F17), the display counterpart to actor2_code. |
| actor2_country_code | text | Actor2CountryCode (F18) — 3-char CAMEO country code of Actor2's NATIONALITY, distinct from the action geography; NULL when the event has only one actor or the source cell is empty. |
| actor2_type1_code | text | Actor2Type1Code (F23) — Actor2's primary CAMEO role/type category (GOV, MIL, BUS, COP, MED, REB, …); the categorical actor-kind filter. |
| is_root_event | boolean | GDELT IsRootEvent (F26), parsed from the source's '0'/'1' via parse_bool01 — true if this event was the lead/primary event of the article it was extracted from (vs. a secondary event mentioned in passing), a common relevance/dedup filter. |
| event_code | text | CAMEO event code (F27), e.g. '043' (host visit) — the specific leaf-level action code in the CAMEO taxonomy describing what Actor1 did to/with Actor2. |
| event_base_code | text | EventBaseCode (F28) — the intermediate 3-digit CAMEO code sitting between the leaf event_code (F27) and the 2-digit event_root_code (F29); a distinct level of the CAMEO taxonomy. |
| event_root_code | text | CAMEO root event code (F29), e.g. '04' (consult) — the top-level (2-digit) category event_code rolls up into; the coarse-grained CAMEO bucket used for aggregate event-type analysis. |
| quad_class | integer | QuadClass (F30): 1 = verbal cooperation, 2 = material cooperation, 3 = verbal conflict, 4 = material conflict — GDELT's coarsest tone/conflict bucketing of event_root_code, tolerant-parsed via parse_i32 (falls through f64 if the source cell has a decimal). |
| goldstein_scale | double precision | GoldsteinScale (F31) — a fixed, CAMEO-code-driven theoretical score from -10 (most destabilizing) to +10 (most cooperative) of this event type's impact on country stability; a per-event-code constant, not a computed sentiment. |
| num_mentions | integer | NumMentions (F32) — total number of source documents (across all monitored languages/outlets) that mentioned this event, including duplicate mentions of the same underlying event within the 15-minute update window; a coverage-volume signal, not article count. |
| num_sources | integer | NumSources (F33) — count of distinct source OUTLETS that mentioned the event; a third coverage-volume metric sitting between num_mentions (total mentions) and num_articles (distinct articles). |
| num_articles | integer | NumArticles (F34) — number of distinct source articles this event was extracted from within the current 15-minute update; lower and more conservative than num_mentions. |
| avg_tone | double precision | AvgTone (F35) — average tone (roughly -100..+100, though empirically almost always within -10..+10) of all documents covering this event, per GDELT's tone dictionary; positive = more positive coverage, negative = more negative. |
| action_geo_country_code | text | ActionGeo_FullName (F53) — the geocoder's human-readable place name of the event's action location (e.g. 'Arundel, West Sussex, United Kingdom'). NOTE: despite the column name, this holds F53 (the full place name), NOT the FIPS country code — the real FIPS10-4 code is in action_geo_country (F54). Kept for backward compatibility. |
| action_geo_type | integer | ActionGeo_Type (F52) — geocode RESOLUTION level of the kept action lat/long: 1=country, 2=US state, 3=US city, 4=world city, 5=world state; qualifies how precise action_geo_lat/long actually are. |
| action_geo_country | text | ActionGeo_CountryCode (F54) — the actual FIPS10-4 COUNTRY code of the event's action location (e.g. 'UK', 'HA'), as distinct from actor nationality; the honest country code the mis-named action_geo_country_code above should have held. |
| action_geo_adm1_code | text | ActionGeo_ADM1Code (F55) — admin-1 (state/province) code of the action location (e.g. 'UKP6'); the geocoded region within the country. |
| action_geo_lat | double precision | Latitude (F57) of the geocoded ActionGeo point — the resolved location of the event's action, at whatever granularity GDELT's geocoder could resolve (point/city/ADM1/country centroid). |
| action_geo_long | double precision | Longitude (F58) of the geocoded ActionGeo point, paired with action_geo_lat. |
| actor1_geo_country_code | text | Actor1Geo_CountryCode (F38) — FIPS10-4 country code of the geocoded location associated with ACTOR1 (as opposed to the action location); a secondary geo point. |
| actor1_geo_lat | double precision | Actor1Geo_Lat (F41) — latitude of Actor1's geocoded location. |
| actor1_geo_long | double precision | Actor1Geo_Long (F42) — longitude of Actor1's geocoded location, paired with actor1_geo_lat. |
| actor2_geo_full_name | text | Actor2Geo_FullName (F45) — human-readable place name of the geocoded location associated with ACTOR2. |
| actor2_geo_country_code | text | Actor2Geo_CountryCode (F46) — FIPS10-4 country code of the geocoded location associated with ACTOR2; a secondary geo point. |
| actor2_geo_lat | double precision | Actor2Geo_Lat (F49) — latitude of Actor2's geocoded location. |
| actor2_geo_long | double precision | Actor2Geo_Long (F50) — longitude of Actor2's geocoded location, paired with actor2_geo_lat. |
| date_added | text | DATEADDED (F60, YYYYMMDDHHMMSS) — the exact 15-minute export-slot stamp this row was published under; process_slot builds the row's own download URL from this same stamp, making it the provable moment the row became publicly fetchable. Kept as an untyped String (not yet parsed into a real timestamp); its date-part is materialized into available_date below. |
| source_url | text | SOURCEURL (F61) — URL of the single news article this GlobalEventID's coding was extracted from; the citation/audit trail back to the original coverage, and the only free-text field carrying the actual story context. |
| available_date | date | PUBLIC-availability date = date-part of date_added (the 15-minute export-slot publish stamp). DB-generated (STORED), read-only; the point-in-time column to filter/join on — NEVER occurred_on's NLP-inferred event date. |
Access gdelt_events
Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.
import obscura
client = obscura.Client("obs_live_…")
df = client.query(
dataset="gdelt_events",
start="2024-01-01",
)
Create a free account Browse all 95 datasets
Frequently asked questions
What is in the gdelt_events dataset?
Geopolitical and economic events extracted from worldwide news by the GDELT project, coded by actor, action and location. One CAMEO-coded actor-action-actor event that GDELT 2.0's NLP pipeline extracted from world news coverage and published in a single 15-minute Event-table export slot, keyed on GDELT's own globally unique GlobalEventID (one physical event can still spawn several GlobalEventIDs across different articles/slots — this table does not dedupe across those).
How do I avoid look-ahead bias with gdelt_events?
Filter on gdelt_events.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — available_date = date_added (F60), the 15-minute export-slot stamp under which this row's export.CSV.zip was published to data.gdeltproject.org — the collector builds the download URL directly from this same stamp, so it is provably the moment the row became publicly fetchable. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.
In what formats can I get gdelt_events?
As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="gdelt_events". The column schema is public at https://api.obscura.trade/v1/catalog/gdelt_events.
How often is gdelt_events updated?
Obscura refreshes gdelt_events on a weekly schedule — that is the most frequent scheduled job that re-collects or re-exports the table. It is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when the publisher makes a row available is described by the availability rule above, and is recorded per row in available_date.