Skip to content
Sources and licensing

Sources and licensing

Where every fact in the dataset comes from, under what terms it was taken, and what that means for you if you use it. This page describes the project’s position; it is not legal advice.

The short version

The code and the data are licensed separately:

LicenceFile
Code — everything except data/MITLICENSE
data/ as a databaseODbL v1.0LICENSE-DATA
data/ individual recordsDbCL v1.0same file

Attribution for the upstream sources lives in NOTICE.

The sources

SourceLicenceWhat it contributes
anime-offline-databaseODbL + DbCLtitles, release year and season, episode counts, cross-provider ids
Anime-Listsnone statedthe AniDB→TVDB id mapping (tvdbId), movie-set grouping hints
WikidataCC0character and staff names — and nothing else; the cast structure around them is authored
This projectODbL (as published here)franchise and series grouping, ids, season and part numbers, absoluteNumber, watch orders

The last row is the part with no upstream at all. Deciding that Fate/Zero and Fate/stay night are two series of one franchise, that Golden Kamuy’s five seasons carry a continuous episode numbering, or that Trigun Stargaze is season two of Stampede — none of that is in any source. It is the project’s editorial work, and it is why the dataset exists.

Where each field comes from

Provenance in this dataset is per field, not per file — every record in data/ mixes all four rows above. This table is the authoritative mapping, keyed by the field path as it appears in a data/series/*.yaml or data/staff/*.yaml record.

Throughout, an authored value always wins: the builder only fills a field the override left empty, merging per field rather than per object. So any field below marked as upstream-filled may instead be the project’s own value where an override supplied one.

FieldFilled fromLicence
franchise.id, series.id, seasons[].id, movies[].id, specials[].id, *.characters[].id, staff[].idthis project — authored slugsODbL
franchise.titles, series.titlesthis project — a franchise or series grouping has no upstream entry, so its title must be authoredODbL
seasons[].titles, movies[].titles, specials[].titlesanime-offline-database — original and ja from the native-script title (or the first native-script synonym), en from the Latin main titleODbL + DbCL
seasons[].number, seasons[].partthis project — editorialODbL
seasons[].releaseYear, seasons[].releaseSeason, movies[].releaseYear, specials[].releaseYearanime-offline-database — its animeSeason blockODbL + DbCL
*.episodes[].airedNumberanime-offline-database — the episode count, expanded to 1…n; the same on a season and on a specialODbL + DbCL
seasons[].episodes[].absoluteNumber, movies[].absoluteNumberthis project — assignAbsoluteNumbers interleaves season episodes and original movies by release order; an alternate cut takes no number of its ownODbL
*.externalIds.anilistIdthis project — the authored join key on whichever node carries it, cross-checked against anime-offline-database’s sources array (see below)ODbL
seasons[].externalIds.anidbId, movies[].externalIds.anidbId, specials[].externalIds.anidbIdanime-offline-database — parsed from its sources array. Only these three node kinds are resolved against itODbL + DbCL
seasons[].externalIds.tvdbId, movies[].externalIds.tvdbId, specials[].externalIds.tvdbIdAnime-Lists — the AniDB→TVDB map, keyed by the anidbId abovenone stated
*.externalIds.wikidataIdthis project — the authored QID join key; in practice only cast nodes carry oneODbL
*.characters[].names, staff[].namesWikidata — the ja label becomes original and ja, the en label becomes enCC0
*.characters[].voiceActors[], *.characters[].appearances[]this project — the cast structure is authored by hand in config/overrides/, with Wikidata used as a research aid rather than extracted fromODbL
movies[].alternateCutOfthis project — Anime-Lists movie sets only report a grouping hint during a build; nothing from them is written to data/ODbL
franchise.watchOrders, numberedthis project — editorialODbL

What the schema allows but the builder never fills

None of the following appears in the current data/. If one ever does, it was authored, and the row above that names its source does not apply to it.

  • *.externalIds.tmdbId, *.releaseDate and *.episodes[].title — nothing in the build writes these anywhere.
  • *.characters[].externalIds.anidbId, *.characters[].externalIds.tvdbId, staff[].externalIds.anidbId, staff[].externalIds.tvdbId — a cast node is resolved by QID against Wikidata, never against anime-offline-database or Anime-Lists, so the two rows above cover season, movie and special only.
  • specials[].absoluteNumber and specials[].episodes[].absoluteNumber — the numbering pass builds its run from seasons and movies, so nothing under a special is ever numbered.
  • specials[].format would default from anime-offline-database’s media type, but the catalogue holds no specials, so it is unused too.

The schema is deliberately permissive here — one externalIds shape is shared by every kind of node — so “the schema allows it” is not evidence that anything fills it.

Why data/ is not split by source

A natural question is whether data/ should be organised as data/anime-offline-database/, data/wikidata/ and so on, so that each directory carries one licence. It should not, for two reasons.

The seam is between fields, not between files. As the table above shows, a single data/series/*.yaml record interleaves all four provenances — titles from anime-offline-database, one tvdbId from Anime-Lists, character names from Wikidata, and the ids, numbering and grouping from this project. Splitting by source would shatter every series across three or four files that consumers must re-join, and would still be coarser than this table, which answers the question at the level it is actually asked.

It would not change the licensing answer, and would misstate it. data/ as a whole is a derivative database of an ODbL source (see below), so ODbL reaches all of it. A directory named data/wikidata/ would read as “this part is CC0, take it freely” — but the arrangement it carries, keyed to ids that exist only because of the project’s editorial structure, is not. One honest licence over the joined result is a stronger statement than four directory names.

The place where one directory per source is the right model is .sources/ — the raw upstream snapshots pulled by builder init, one file per source, untouched and unjoined. data/ is the joined output, and joining is the point of it.

Why the data is under ODbL

data/ is built from anime-offline-database, so it is a derivative database of an ODbL source, and ODbL’s share-alike term reaches derivative databases — not just verbatim copies. The dataset is therefore offered on the same terms it was received under. That is an obligation inherited from the source, not a preference.

Two consequences worth being explicit about:

  • Sharing a modified dataset publicly means sharing it under ODbL too. If you extend, correct or re-derive data/ and make it publicly available, the result carries the same licence.
  • The terms travel with binaries. dataset.go embeds data/ with go:embed, so a compiled cmd/api binary — or a deployment of it — contains the database. It is not only the YAML files that are covered.

A Produced Work built from the data — a chart, an article, an app screen — is treated differently by ODbL and needs attribution rather than share-alike. The dataset itself, and an API that returns it, are not Produced Works.

Anime-Lists has no stated licence

The project publishes no licence file. What the build takes from it is bare identifier pairs — numbers linking one public database to another — which this project treats as facts rather than protected expression, and which are widely vendored on that basis. That reasoning is stated plainly rather than hidden because it is the weakest link in the chain: if you are redistributing this dataset in a context where that matters, reach your own view.

Why AniList ids appear but AniList data does not

AniList’s Terms of Service prohibit using its API as a backup or data storage service and prohibit mass collection, so the build never calls AniList and no AniList content is stored or served. There is no AniList endpoint in config.yaml.

The anilistId on every node is an identifier parsed out of the cross-reference URLs that anime-offline-database publishes — the same array that yields anidbId, myAnimeListId and kitsuId. It is a join key into the ODbL source, not AniList data.

This is the point of the “facts, not expression” rule the dataset follows throughout: the dataset stores ids, names and structure, and leaves synopses, artwork, ratings and biographies to be fetched live at runtime from whichever service the consumer has a right to use. See Using the dataset.

If you redistribute this dataset

Keep NOTICE intact, credit this project and the upstream sources, and offer any publicly released derivative database under ODbL. If you only publish a Produced Work built from the data, attribution is enough.