Skip to main content

HistWarDB 🌍⚔️

Historical & Sovereign War Dataset powered by Wikidata

Tests Python Version License: MIT DOI

HistWarDB is a Python toolkit that extracts, cleans and analyses war participation data from Wikidata, from 1700 to the present, for both modern sovereign states and historical states. It produces a table of who took part in which war and a Country × Year × Month panel derived from it, with month/day precision kept wherever Wikidata actually records it.

The coding rules are written down in the codebook, and agreement with Correlates of War and UCDP/PRIO is measured in the validation report. Please read both before using the data for research: coverage is bounded by Wikidata.


Key Features

  • Wars and their subclasses: every Wikidata item typed as war or a subclass (world war, civil war, proxy war, ...), minus peacekeeping missions, military exercises and fictional wars.
  • Conflict structure: each conflict's Wikidata type, the war it is part of, and its top-level war; fronts and campaigns can be kept, dropped or rolled up into their war.
  • Sides where Wikidata has them: coalition participants (Allies, Axis, Central Powers, ...) are expanded into member states with a side, giving a dyadic table of opposing states.
  • State belligerents only: participants must be typed as sovereign state, historical country or country.
  • Stable identifiers: every conflict and country carries its Wikidata QID; countries also carry Correlates of War and Gleditsch–Ward codes from a bundled crosswalk, and an ISO 3166-1 alpha-3 code where Wikidata has one.
  • Lifespan-aware: a state is never counted at war in a year in which it did not exist, and the panel says which country-years fall outside a state's lifespan.
  • Explicit uncertainty: conflicts with no recorded end date are flagged, and the rule used to extend them is a parameter.
  • Fails loudly: queries are retried with backoff; a chunk that cannot be fetched raises an error instead of silently leaving a gap.
  • Frozen snapshots: save and reload a dataset with retrieval metadata and a checksum, so published results can be reproduced.
  • Analytical views and plots: long format, binary matrix, conflict names, lists, and a Plotly heatmap.

Project layout

src/histwardb/
    query.py      # SPARQL query construction (pure, no I/O)
    core.py       # HistWarDB class: fetch, parse, clean, analytical views
    relations.py  # part-of chains, coalitions, sides, dyads (pure)
    data/         # COW / Gleditsch-Ward crosswalk
data/snapshots/  # frozen, checksummed copies of the dataset
scripts/       # crosswalk builder, validation against COW and UCDP
validation/    # validation report
tests/         # pytest suite (parsing, filtering, views, mocked network)
CODEBOOK.md    # coding rules and column definitions
HistWarDB.ipynb  # usage demo notebook (Colab-compatible)

Installation

pip install git+https://github.com/VincenzoManto/histwardb.git

For local development (editable install + test/lint tooling):

git clone https://github.com/VincenzoManto/histwardb.git
cd histwardb
pip install -e ".[dev]"

Quick Start

from histwardb import HistWarDB

# Fetch live from Wikidata, 1700 to 2026 (about 20 queries, 2-3 minutes)
gwd = HistWarDB(start_year=1700, end_year=2026)

# Who took part in what: one row per conflict x country, with QIDs and dates
print(gwd.participations.head())

# Country x Year x Month panel for specific countries (exact match on name, QID or ISO code)
france_uk_wars = gwd(countries=["France", "United Kingdom"], view="long", only_in_war=True)

# Binary matrix for a period (year or "YYYY-MM"); months outside the state's lifespan read <NA>
binary_view = gwd(countries="German Empire", view="binary", from_date=1900, to_date=1925, only_existing=True)

# Heatmap for the 15 states with most war-years
gwd.plot_heatmap(top_n=15, from_year=1800, to_year=2026).show()

Reproducible use: snapshots

Wikidata changes every day, so two live fetches can differ. For anything you intend to publish, work from a frozen snapshot and cite it:

# Load the snapshot shipped with the repository (no network access)
gwd = HistWarDB.from_snapshot("data/snapshots/2026-10-14")

# Or freeze your own fetch
gwd = HistWarDB(start_year=1700, end_year=2026)
gwd.save_snapshot("my_snapshot")   # participations.csv + metadata.json

metadata.json records the retrieval time, parameters, query text, row counts and a SHA-256 checksum that from_snapshot verifies.

Wars, fronts and sides

gwd = HistWarDB.from_snapshot("data/snapshots/2026-10-14")
gwd.conflicts                       # one row per conflict: type, parent/root war, dates, death toll
gwd.dyads                           # pairs of states on opposing coalition sides
HistWarDB(subconflicts="roll_up")   # attribute fronts and campaigns to their top-level war
HistWarDB(series_of_wars="drop")    # leave out "series of wars" items such as the Balkan Wars

Sides come only from coalitions that Wikidata lists as participants, so most conflicts have none; see the codebook.

Conflicts with no end date

Some Wikidata conflicts have a start date and no end date. The missing_end parameter decides how far they are extended:

HistWarDB(missing_end="heuristic")   # default: to the present if started 1800 or later, else 5 years
HistWarDB(missing_end="start_only")  # conservative: start year only
HistWarDB(missing_end="open")        # always to the present
HistWarDB(missing_end="drop")        # discard them

Whatever the rule, affected rows are flagged (duration_estimated in the participation table, Duration_Estimated and War_Imputed in the panel), so you can filter them out. The cutoff year and pre-cutoff duration of the default rule are parameters too (heuristic_cutoff_year, pre_cutoff_duration_years).

Severity threshold

HistWarDB(min_casualties=1000)  # drop conflicts with a recorded death toll below 1,000

Conflicts without a recorded toll (Wikidata P1120) are kept. Few conflicts have one, so this filter currently changes little; see the codebook.


Supported Views (view parameter)

  • "long": tidy DataFrame with Country, Year, Month, War_State, Active_Conflicts, Duration_Estimated, Country_QID, ISO3, State_Exists, War_Imputed. Month resolution only reflects real Wikidata precision -- a conflict known only to the year fills all 12 months.
  • "binary": countries as rows, "YYYY-MM" periods as columns, 1 = at war, 0 = no war recorded.
  • "names": same shape, with the names of the active conflicts.
  • "list": alphabetical list of the conflict names under the current filters.
  • "countries" / "conflicts": sorted lists of countries at war, or of conflicts, under the current filters.

from_date/to_date accept a year ("YYYY" or int) or a specific month ("YYYY-MM"); an omitted month defaults to the start/end of the year.

War_State = 0 means "no war recorded in Wikidata", not "peace". Use State_Exists (or only_existing=True) to separate months in which the state did not exist. See the codebook.


Testing

The default test suite never queries the live Wikidata endpoint. The HistWarDB class accepts an injectable session object for its HTTP calls, and all parsing/filtering logic is pure and tested against static fixtures:

pip install -e ".[dev]"
pytest --cov=histwardb

A small opt-in suite checks the real endpoint: that every QID constant means what the code says, and that well-known wars, states and sides come back. It also runs weekly in CI (.github/workflows/live-tests.yml).

pytest -m network

See CONTRIBUTING.md for details.


Citation

If you use HistWarDB in your academic research, working paper, or data science project, please cite it using the following format (also available in machine-readable form in CITATION.cff), and state which snapshot you used:

@software{histwardb2026,
  author = {Manto, Vincenzo and Dal Cero, Riccardo},
  title = {HistWarDB: A Dynamic Wikidata-Based Historical War Dataset},
  year = {2026},
  url = {https://github.com/VincenzoManto/histwardb}
}

License

Code is distributed under the MIT License. See LICENSE for more information. The data comes from Wikidata, which is released under CC0.

Metadata

Release files for histwardb 0.5.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for histwardb 0.5.2
File Size Uploaded
histwardb-0.5.2.tar.gz 57.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for histwardb 0.5.2
File Interpreter ABI Platform
histwardb-0.5.2-py3-none-any.whl Python 3 none any Details

Total release size: 98.3 kB

Release files / histwardb-0.5.2.tar.gz

Download URL histwardb-0.5.2.tar.gz
Size 57.9 kB
Tags Source
SHA-256 checksum
How to use checksums
5eb083bdb77f016cfef40d2316ceff021032b81c43e8f0e1e1cdb09fad1b1bf6
BLAKE2b-256 checksum
How to use checksums
4f10a685f543ffddc24c0e085065557be07aaac822ca5a7680e4ff4b559eedb1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

Release files / histwardb-0.5.2-py3-none-any.whl

Download URL histwardb-0.5.2-py3-none-any.whl
Size 40.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d2b27631b0d0b5918452fd7d18e5ed931d07c37d81d6b23f90e12b344baa552
BLAKE2b-256 checksum
How to use checksums
1b73a4b049ef7554f692028808ac0601ff9ad76087b224968048a8ec1be0dec9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.2 This release

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page