Skip to content

Repository files navigation

wiki-entity

Fetch and normalize entities from Wikidata, Wikipedia and DBpedia.

  • Zero runtime dependencies — built on fetch, ESM + CommonJS, fully typed.
  • Batches, retries and rate-limit aware by default.
  • Flattens Wikidata's deeply nested claim format into something you can read.
npm install wiki-entity

Requires Node.js >= 20.19.

Usage

import { getEntities, setUserAgent } from "wiki-entity";

setUserAgent("MyApp/1.0 (https://myapp.example; contact@myapp.example)");

// by Wikipedia article title
const [europe] = await getEntities({ language: "en", titles: ["Europe"] });

// by Wikidata id, with a Wikipedia summary and resolved claim labels
const [einstein] = await getEntities({
  language: "en",
  ids: ["Q937"],
  extract: 2,
  claims: "all"
});

einstein.label; // "Albert Einstein"
einstein.extract; // "Albert Einstein was a German-born theoretical physicist…"
einstein.claims.P569.label; // "date of birth"
einstein.claims.P569.values[0].value_string; // "1879-03-14"

CommonJS works too:

const { getEntities } = require("wiki-entity");

User-Agent

Wikimedia's User-Agent policy requires every client to identify itself. Generic agents get throttled or blocked with HTTP 429. Set yours once at startup:

import { setUserAgent } from "wiki-entity";

setUserAgent("MyApp/1.0 (https://myapp.example; contact@myapp.example)");

or via the environment:

WIKI_ENTITY_USER_AGENT="MyApp/1.0 (https://myapp.example; contact@myapp.example)"

API

getEntities(params): Promise<WikiEntity[]>

Fetches entities from Wikidata and enriches them from Wikipedia and DBpedia. Results follow the order of the requested ids/titles; entities that do not exist are omitted.

Param Type Default Description
ids string[] Wikidata ids, max 500. Either this or titles is required.
titles string[] Wikipedia article titles in language, max 500.
language string "en" Language of titles and of the resulting label/description.
languages string[] Extra languages to populate labels with.
props string[] all info, sitelinks, aliases, labels, descriptions, claims, datatype.
claims string none none, item, property or all — how deeply to resolve claim labels.
extract number Sentences of the Wikipedia lead section to fetch.
types boolean | string[] false true for DBpedia ontology types, or an array of prefixes to keep (e.g. ["dbo", "schema"]).
redirects boolean false Titles of Wikipedia articles that redirect to this entity.
categories boolean false The article's non-hidden categories.
wikiPageId boolean true Fetch the Wikipedia pageid.
httpTimeout number 15000 Per-request timeout in milliseconds.
signal AbortSignal Cancels every underlying request.
followEntityRedirects boolean true Resolve Wikidata items that were merged into another item.

extract, redirects and categories need the entity to have a sitelink for language, so keep sitelinks in props when you narrow it.

Note redirects and followEntityRedirects are unrelated: the first fetches the titles of Wikipedia articles pointing at this entity, the second controls whether a merged-away Wikidata item resolves to the item that replaced it.

mapRedirects(titles, lang): Promise<Record<string, string>>

Resolves Wikipedia redirect titles to the articles they point at. Only titles that really are redirects appear in the result.

await mapRedirects(["Brashov"], "ro"); // { Brashov: "Brașov" }

getSimpleEntities(params, options?): Promise<SimpleEntity[]>

getEntities followed by convertToSimpleEntity, in one call. Takes the same params, plus an optional { defaultType }.

const entities = await getSimpleEntities({
  language: "en",
  ids: ["Q937"],
  types: true,
  extract: 2
});

entities[0].name; // "Albert Einstein"
entities[0].type; // SimpleEntityType.PERSON

Prefer this over calling the two by hand: it takes the language from params, so it cannot drift. Converting with a different language than you fetched with silently mixes them — name and about come from the fetch, while wikiPageTitle is read from the sitelinks of whichever language you passed.

convertToSimpleEntity(wikiEntity, lang, options?): SimpleEntity

Flattens a single WikiEntity into the compact shape. Use it when you already have entities from getEntities.

Escape hatches

For what getEntities does not cover. Everything else in the package is an implementation detail and may change without a major release.

Export Purpose
queryPages(options) Query Wikipedia articles directly — batched, continuation-safe.
simplifyEntity(lang, raw, options?) Flatten a raw wbgetentities entity you fetched yourself.
getEntityTypesByNames(names, options?) DBpedia ontology types for English Wikipedia titles.
setDbpediaEndpoint / getDbpediaEndpoint Point type lookups at a DBpedia mirror.
setUserAgent / getUserAgent The User-Agent sent with every request.

queryPages(options)

Talks to Wikipedia only — no Wikidata lookup, no entity ids. Use it when you have article titles and want their summaries, redirects or categories.

import { queryPages } from "wiki-entity";

const { pages } = await queryPages({
  lang: "en",
  titles: ["Chișinău", "Italy"],
  extract: 2,
  followRedirects: true
});

for (const page of pages) {
  console.log(page.pageid, page.title, page.extract);
}
Option Type Description
lang string Wikipedia language code, e.g. "en". Required.
titles string[] Article titles. Required; batched automatically.
extract number Sentences of the lead section to fetch.
redirects boolean Titles of articles redirecting to each page.
categories boolean Each article's non-hidden categories.
followRedirects boolean Resolve titles that are themselves redirects.
httpTimeout number Per-request timeout in milliseconds.
signal AbortSignal Cancels every underlying request.

It handles the parts of the MediaWiki API that are easy to get wrong: titles are batched (50 per request, or 20 when extract is set, since the API refuses more intro extracts than that), and paginated continue responses are followed, so long redirects and categories lists are not truncated at the first page.

pages is not in the order you asked for, and MediaWiki normalizes titles and follows redirects, so the title that comes back may not be the one you sent. Two maps tie the results back to your input:

const { pages, resolved, requestedTitleOf } = await queryPages({
  lang: "en",
  titles: ["Kishinev"],
  categories: true,
  followRedirects: true
});

pages[0].title; // "Chișinău" — the redirect target
resolved.get("Kishinev"); // { title: "Chișinău", redirected: true }
requestedTitleOf.get("Chișinău"); // "Kishinev"

Earlier releases had getExtract, getExtracts and getRedirects for this. They were thin wrappers that only ever handled one request's worth of titles:

// before                                    // now
getExtracts({ lang, titles, sentences: 2 }); // queryPages({ lang, titles, extract: 2 })
getExtract(lang, title, 2); // queryPages({ lang, titles: [title], extract: 2 })
getRedirects(lang, title); // queryPages({ lang, titles: [title], redirects: true })

getExtract returned a single object or null; the equivalent is (await queryPages({ lang, titles: [title], extract: 2 })).pages[0] ?? null.

Errors

All errors extend WikiEntityError:

  • HttpError — non-2xx status, network failure or timeout. status, url and retryable describe it; 429 and 5xx are retried automatically.
  • ApiError — the request succeeded but MediaWiki reported an error (code).

Bad arguments throw a plain TypeError.

DBpedia types are best-effort enrichment: if the endpoint is unreachable, types is simply left unset instead of failing the call.

WikiEntity

WikiEntity is a flattened Wikidata item, plus the extras pulled from Wikipedia and DBpedia.

type WikiEntity = {
  id: string;
  label?: string;
  labels?: Record<string, string>;
  description?: string;
  descriptions?: Record<string, string>;
  aliases?: string[];
  sitelinks?: Record<string, string>;
  claims?: Record<string, WikidataProperty>;
  /** Wikipedia page id (not Wikidata's). */
  pageid?: number;
  extract?: string;
  types?: string[];
  redirects?: string[];
  categories?: string[];
  redirectsToId?: string;
  redirectsFromId?: string;
};

type WikidataProperty = {
  id: string;
  label?: string;
  description?: string;
  values: WikidataPropertyValue[];
};

type WikidataPropertyValue = {
  datatype: string;
  /** Scalar for simple datatypes, the raw object for time/quantity/coordinates. */
  value: string | number | object;
  /** Readable rendering of a structured `value`. */
  value_string?: string;
  rank?: "preferred" | "normal" | "deprecated";
  label?: string;
  description?: string;
  qualifiers?: Record<string, WikidataProperty> | null;
};

Notes on the claim values:

  • Statements Wikidata marks deprecated are dropped, and preferred ones are sorted first, so values[0] is the value Wikidata recommends.
  • Dates render at their stated precision and keep the sign of BCE years: -0044-03-15.
  • Coordinates render as "47.0105,28.8638".
  • Labels fall back to Wikidata's mul ("multiple languages") code, which is where many items now keep a name that is spelled the same everywhere.

SimpleEntity

enum SimpleEntityType {
  EVENT = "E",
  ORG = "O",
  PERSON = "H",
  PLACE = "P",
  PRODUCT = "R",
  WORK = "W"
}

type SimpleEntity = {
  /** Always set. */
  lang: string;
  /** Always set. */
  wikiDataId: string;
  name?: string;
  description?: string;
  about?: string;
  wikiPageId?: number;
  wikiPageTitle?: string;
  type?: SimpleEntityType;
  types?: string[];
  countryCodes?: string[];
  data?: Record<string, string[]>;
  categories?: string[];
  redirectsToId?: string;
  redirectsFromId?: string;
};

The entity type is resolved from the DBpedia ontology types first, then from the P31 claims against the generated Wikidata class tables, and finally from the opening words of the extract.

Generated data

data/countries.json and data/entity-types.json are derived from Wikidata and checked in. Regenerate them against the live query service with:

npm run data:countries
npm run data:entity-types

data:entity-types verifies a set of known classifications before writing, so a bad expansion fails loudly instead of silently degrading type detection.

Development

npm install
npm test              # unit tests, fully mocked
npm run test:integration   # hits the live Wikimedia and DBpedia APIs
npm run check         # format, lint, typecheck, test, build

License

ISC

About

Wiki(pedia/data/dbpedia) entity fetcher

Topics

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages