npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@api-wrappers/anilist-wrapper

v3.0.0

Published

Typed AniList GraphQL wrapper for anime, manga, characters, staff, users, media lists, and raw GraphQL requests.

Readme

@api-wrappers/anilist-wrapper is a typed AniList GraphQL wrapper for anime, manga, characters, staff, users, media lists, and raw GraphQL escape hatches. It gives TypeScript and Bun or Node.js apps dedicated services for common AniList workflows while keeping direct GraphQL access available when AniList supports a field the wrapper has not modeled yet.

Install

npm install @api-wrappers/anilist-wrapper
# or
bun add @api-wrappers/anilist-wrapper
# or
pnpm add @api-wrappers/anilist-wrapper
# or
yarn add @api-wrappers/anilist-wrapper

Quick Start

import { Anilist } from "@api-wrappers/anilist-wrapper";

const anilist = new Anilist();
const anime = await anilist.anime.getAnimeById(16498);

console.log(anime.Media?.title?.userPreferred);

Why Use This Instead Of Raw GraphQL?

  • Typed services cover common AniList resources without repeating operation strings in every app.
  • Generated GraphQL schema and operation types are exported from the package.
  • The client sets the AniList endpoint, JSON headers, optional bearer auth, and retry behavior for AniList rate-limit responses.
  • Shared fragments keep anime, manga, staff, character, user, and list response shapes consistent across convenience methods.
  • The raw GraphQL service stays available for new AniList fields, one-off queries, or app-specific projections.

Why Not Just Use graphql-request?

Use graphql-request or another generic GraphQL client if all you need is a small transport layer and you want to own every query string yourself.

Use this wrapper when you want AniList-specific service methods, generated operation types, documented examples, built-in auth header setup, and a stable set of convenience APIs for anime, manga, characters, staff, users, and media lists. You can still run custom operations through anilist.graphql.request.

Practical Examples

Create an unauthenticated client

import { Anilist } from "@api-wrappers/anilist-wrapper";

const anilist = new Anilist();

Most public anime, manga, character, staff, and username-based user reads work without a token.

Create an authenticated client

import { Anilist } from "@api-wrappers/anilist-wrapper";

const anilist = new Anilist(process.env.ANILIST_TOKEN);

Use an authenticated client for private user data, favorites, and media list mutations.

Anime and manga favorite mutations use toggleFavorite(...). The older toggleFavourite(...) spelling remains available as a backwards-compatible alias.

Get anime by ID

const anime = await anilist.anime.getAnimeById(16498);

console.log(anime.Media?.title?.userPreferred);
console.log(anime.Media?.siteUrl);

Search anime

const results = await anilist.anime.getAnimeBySearch("Frieren", 1, 5);

for (const media of results.Page?.media ?? []) {
	console.log(media?.title?.userPreferred, media?.startDate?.year);
}

Select only the fields you need

Pass a select object to read endpoints or mutations when you want an exact response shape. Selected calls use normalized lowercase roots:

const { media } = await anilist.anime.getAnimeById(16498, {
	select: {
		media: {
			id: true,
			title: { userPreferred: true },
			startDate: { year: true },
		},
	},
});

const { page } = await anilist.anime.getAnimeBySearch("Frieren", 1, 5, {
	select: {
		page: {
			pageInfo: { currentPage: true, hasNextPage: true },
			media: { id: true, title: { userPreferred: true } },
		},
	},
});

console.log(media?.title?.userPreferred);
console.log(page?.pageInfo?.hasNextPage);

See the selection migration guide for all endpoint roots, mutation examples, and legacy direct-select compatibility.

Get manga

const manga = await anilist.manga.getMangaById(30013);

console.log(manga.Media?.title?.userPreferred);
console.log(manga.Media?.chapters);

Get character

const character = await anilist.character.getCharacterById(1);

console.log(character.Character?.name?.full);
console.log(character.Character?.siteUrl);

Get staff

const staff = await anilist.staff.getStaffById(95269);

console.log(staff.Staff?.name?.full);
console.log(staff.Staff?.primaryOccupations?.filter(Boolean).join(", "));

Get a user anime list

import { MediaListStatus } from "@api-wrappers/anilist-wrapper";

const list = await anilist.user.getUserAnimeListByUsername(
	"example_user",
	MediaListStatus.Current,
);

for (const group of list.MediaListCollection?.lists ?? []) {
	console.log(group?.entries?.length ?? 0);
}

Update a media list entry

import { Anilist, MediaListStatus } from "@api-wrappers/anilist-wrapper";

const anilist = new Anilist(process.env.ANILIST_TOKEN);

const saved = await anilist.mediaList.saveEntry({
	mediaId: 16498,
	status: MediaListStatus.Current,
	progress: 1,
	score: 8,
});

console.log(saved.SaveMediaListEntry?.id);

saveEntry creates or updates the authenticated user's media list entry. AniList requires a valid access token for this mutation.

Raw GraphQL request

import { Anilist, gql } from "@api-wrappers/anilist-wrapper";

const anilist = new Anilist();

const data = await anilist.graphql.request<{
	GenreCollection: Array<string | null> | null;
}>(gql`
	query Genres {
		GenreCollection
	}
`);

console.log(data.GenreCollection);

Common App Use Cases

  • Anime tracker: search anime, read details, and save watch progress.
  • Manga tracker: search manga, inspect chapters or volumes, and update reading progress.
  • User list importer: read public anime or manga lists by username and map list entries into your app.
  • Recommendation app: combine media details, genres, tags, rankings, relations, and AniList recommendations.
  • AniList dashboard: render user profile data, statistics, current lists, and quick links to AniList pages.

Services

| Property | Use it for | | --- | --- | | anilist.anime | Anime lookup, search, trending, popular, genre, relations, characters, staff, recommendations, favorites | | anilist.manga | Manga lookup, search, trending, popular, genre, relations, characters, staff, recommendations, favorites | | anilist.character | Character lookup, birthdays, favorites | | anilist.staff | Staff lookup, birthdays, favorites | | anilist.user | User profiles, public lists by username, authenticated list/stat queries by user ID | | anilist.media | Generic anime/manga media lookup and list access | | anilist.mediaList | Media list entry lookup, save, and delete | | anilist.graphql | Any AniList GraphQL query or mutation |

Runtime Support

The package ships ESM, CommonJS, and TypeScript declaration output from dist/. It is developed and tested with Bun, and it can be used from modern Node.js runtimes that support the package exports field and fetch-compatible HTTP behavior through @api-wrappers/api-core.

Generated GraphQL Types

GraphQL schema and operation types are generated into src/__generated__/ from codegen.yml, the query documents in src/queries/, and the fragments in src/fragments/. Do not edit generated files by hand.

Run bun run codegen when you add or change GraphQL operations, fragments, or schema-driven types. The codegen step fetches the AniList schema, writes the generated files, then runs scripts/patch-codegen.ts so the generated SDK uses the package's @api-wrappers/api-core GraphQL client shape.

Docs And Examples

Run examples directly from this repo:

bun examples/basic-anime.ts
bun examples/manga-workflow.ts
bun examples/characters-and-staff.ts
bun examples/raw-graphql.ts
ANILIST_TOKEN=... ANILIST_USERNAME=... bun examples/authenticated-user.ts

Development

bun install
bun run check
bun run typecheck
bun run test
bun run build
bun run verify

bun run test runs deterministic non-network contract tests. Use bun run test:live for the live AniList smoke tests, which can be affected by network availability, upstream API state, and rate limits. bun run verify runs the local checks, typecheck, build, and Bun pack dry-run.

Use bun run codegen only when GraphQL operations, fragments, or generated types need to be refreshed.

Release Process

Maintainers use Changesets for releases. Add a changeset for user-facing changes with bun run changeset; merging the generated version PR on main publishes to npm and creates GitHub release notes through the release workflow.

Contributing

Issues and pull requests are welcome. Read CONTRIBUTING.md, CODE_OF_CONDUCT.md, and SECURITY.md before contributing.

License

MIT