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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@spkrbox/anilist

v1.0.4

Published

A modern TypeScript wrapper for the AniList GraphQL API

Downloads

9

Readme

npm version License: MIT TypeScript

📋 Table of Contents

📦 Installation

Install the package using npm:

npm install @spkrbox/anilist

Or using yarn:

yarn add @spkrbox/anilist

Or using bun:

bun add @spkrbox/anilist

🚀 Basic Usage

Here's a simple example to get you started:

import { AniList, MediaType } from '@spkrbox/anilist'

// Create a new client instance
const client = new AniList()

async function searchAnime(term: string) {
    const results = await client.media.search({
        search: term,
        type: MediaType.ANIME,
        perPage: 5,
    })

    results.media.forEach((anime) => {
        console.log(`${anime.title.native} - ${anime.id} - ⭐ ${anime.averageScore}`)
    })
}

searchAnime('Solo Leveling')

// 俺だけレベルアップな件 - 151807 - ⭐ 82
// 俺だけレベルアップな件 -ReAwakening- - 184694 - ⭐ 81
// 俺だけレベルアップな件 Season 2 -Arise from the Shadow- - 176496 - ⭐ 87

// Get anime by ID
async function getAnimeById(id: number) {
    const anime = await client.media.getById(id)

    console.log(`Title: ${anime.title.romaji} (${anime.title.english || 'No English title'})`)
    console.log(`Episodes: ${anime.episodes || 'Unknown'}`)
    console.log(`Genres: ${anime.genres?.join(', ') || 'None listed'}`)
}

getAnimeById(1) // Cowboy Bebop

// Title: Cowboy Bebop (Cowboy Bebop)
// Episodes: 26
// Genres: Action, Adventure, Drama, Sci-Fi

🔐 Authentication

For actions that require authentication (like accessing a user's private data or modifying lists), you'll need to authenticate your client:

import { createAuthenticatedClient } from '@spkrbox/anilist'

async function authenticatedExample() {
    // Create an authenticated client
    const client = await createAuthenticatedClient('CLIENT_ID', 'CLIENT_SECRET')

    // Get the current user's information
    const viewer = await client.user.getViewer()
    console.log(`Authenticated as: ${viewer.name}`)

    // Get the user's anime list
    const animeList = await client.lists.getAnimeList({ userName: viewer.name })
    animeList.lists?.forEach((list) => {
        console.log(`${list.name} - ${list.entries?.length}`)
    })
}

authenticatedExample()

// Authenticated as: chaptrhouse
// Planning - 1
// Completed - 30
// Dropped - 1

To set up authentication, you'll need to:

  1. Register an application on AniList: https://anilist.co/settings/developer
  2. Get your Client ID and Client Secret
  3. Use the createAuthenticatedClient function with your credentials

For more details on authentication flows, see the Authentication section below.

📚 API Reference

Client

The main AniList client is your entry point to all API services:

import { AniList } from '@spkrbox/anilist'

const client = new AniList()

The client instance provides access to all service modules:

// Examples of accessing different services
const animeData = await client.media.getById(1)
const userData = await client.user.getById(1)
const characterData = await client.character.getById(1)

Media Service

The Media service allows you to access anime and manga data:

// Get anime by ID
const anime = await client.media.getById(1)

// Search for media
const searchResults = await client.media.search({
    search: 'Attack on Titan',
    type: MediaType.ANIME,
})

// Get trends
const trends = await client.media.getTrends(176496, 1, 10, true) // mediaId, pageNumber, perPage, releasing

// {
//   pageInfo: {
//     total: 500,
//     currentPage: 1,
//     lastPage: 50,
//     hasNextPage: true,
//     perPage: 10,
//   },
//   nodes: [
//     {
//       mediaId: 176496,
//       date: 1736521200,
//       trending: 2326,
//       averageScore: 85,
//       popularity: 94446,
//       inProgress: 50463,
//       releasing: true,
//       episode: 2,
//     }, {
//       mediaId: 176496,
//       date: 1736607600,
//       trending: 27095,
//       averageScore: 85,
//       popularity: 95979,
//       inProgress: 52691,
//       releasing: true,
//       episode: 2,
//     },
//     ...
//   ],
// }

User Service

Access user profiles and data:

// Get user by ID
const user = await client.user.getById(1)

// Get user by name
const userByName = await client.user.getByName('username')

// Get current authenticated user
const viewer = await client.user.getViewer()

// Search for users
const users = await client.user.search({
    search: 'chaptrhouse',
    perPage: 10,
})

// {
//   pageInfo: {
//     total: 1,
//     currentPage: 1,
//     lastPage: 1,
//     hasNextPage: false,
//     perPage: 10,
//   },
//   users: [
//     {
//       id: 7233249,
//       name: "chaptrhouse",
//       about: null,
//       avatar: [Object ...],
//       bannerImage: null,
//       isFollowing: false,
//       isFollower: false,
//       siteUrl: "https://anilist.co/user/7233249",
//       donatorTier: 0,
//       donatorBadge: "Donator",
//       createdAt: 1742184409,
//     }
//   ],
// }

Character Service

Access character data:

// Get character by ID
const character = await client.character.getById(1)

// Search for characters
const characters = await client.character.search({
    search: 'Levi',
    perPage: 10,
})

// {
//   id: 1,
//   name: {
//     first: "Spike",
//     last: "Spiegel",
//     full: "Spike Spiegel",
//     native: "スパイク・スピーゲル",
//     alternative: [ "Spike Spike", "Swimming Bird" ],
//     alternativeSpoiler: [],
//   },
//   image: {
//     large: "https://s4.anilist.co/file/anilistcdn/character/large/b1-ChxaldmieFlQ.png",
//     medium: "https://s4.anilist.co/file/anilistcdn/character/medium/b1-ChxaldmieFlQ.png",
//   },
//   description: "__Height:__ 185 cm   \n\nSpike Spiegel is a tall and lean 27-year-old bounty hunter born on Mars.",
//   gender: "Male",
//   dateOfBirth: {
//     year: 2044,
//     month: 6,
//     day: 26,
//   },
//   age: "27",
//   bloodType: null,
//   siteUrl: "https://anilist.co/character/1",
//   favourites: 12130,
//   isFavourite: false,
//   media: {
//     nodes: [
//       [Object ...], [Object ...], [Object ...], [Object ...], [Object ...]
//     ],
//   },
// }

Staff Service

Access staff members (voice actors, directors, etc.):

// Get staff by ID
const staff = await client.staff.getById(1)

// Search for staff
const staffMembers = await client.staff.search({
    search: 'Miyazaki',
    perPage: 10,
})

Studio Service

Access animation studios:

// Get studio by ID
const studio = await client.studio.getById(1)

// Search for studios
const studios = await client.studio.search({
    search: 'Ghibli',
    perPage: 10,
})

// {
//   pageInfo: {
//     total: 1,
//     currentPage: 1,
//     lastPage: 1,
//     hasNextPage: false,
//     perPage: 10,
//   },
//   studios: [
//     {
//       id: 21,
//       name: "Studio Ghibli",
//       isAnimationStudio: true,
//       favourites: 11574,
//       siteUrl: "https://anilist.co/studio/21",
//       media: [Object ...],
//     }
//   ],
// }

List Service

Access and manage user media lists:

// Get a user's anime list
const animeList = await client.lists.getAnimeList({
    userName: 'chaptrhouse',
})

// Get a user's manga list
const mangaList = await client.lists.getMangaList({
    userName: 'chaptrhouse',
})

// Get a specific list entry
const user = await client.user.getByName('chaptrhouse')
const entry = await client.lists.getMediaListEntry(user.id, 1) // Get chaptrhouse's list entry for Cowboy Bepop

// {
//   id: 5318,
//   userId: 1,
//   mediaId: 1,
//   status: "COMPLETED",
//   score: 2,
//   progress: 26,
//   progressVolumes: null,
//   repeat: 0,
//   priority: 0,
//   private: false,
//   notes: null,
//   startedAt: {
//     year: null,
//     month: null,
//     day: null,
//   },
//   completedAt: {
//     year: 2017,
//     month: 11,
//     day: 24,
//   },
//   updatedAt: 1511491706,
//   createdAt: 1397079561,
//   media: {
//     id: 1,
//     title: {
//       userPreferred: "Cowboy Bebop",
//       romaji: "Cowboy Bebop",
//       english: "Cowboy Bebop",
//       native: "カウボーイビバップ",
//     },
//     coverImage: {
//       large: "https://s4.anilist.co/file/anilistcdn/media/anime/cover/medium/bx1-CXtrrkMpJ8Zq.png",
//       medium: "https://s4.anilist.co/file/anilistcdn/media/anime/cover/small/bx1-CXtrrkMpJ8Zq.png",
//     },
//     type: "ANIME",
//     format: "TV",
//     status: "FINISHED",
//     episodes: 26,
//     chapters: null,
//     volumes: null,
//     averageScore: 86,
//     popularity: 385533,
//     nextAiringEpisode: null,
//   },
// }

Forum Service

Access forum threads and comments:

// Get recent threads
const threads = await client.forum.getThreads({
    page: 1,
    perPage: 20,
})

// Get thread by ID
const thread = await client.forum.getThread(1)

// Get thread comments
const comments = await client.forum.getThreadComments({
    threadId: 1,
    page: 1,
    perPage: 20,
})

Activity Service

Access user activity feeds:

// Get activities
const activities = await client.activity.getActivities()

// Get activity by id
const activity = await client.activity.getActivity(activities[0].id)

Notification Service

Manage user notifications:

const client = await createAuthenticatedClient('CLIENT_ID', 'CLIENT_SECRET')

const notifications = await client.notification.getNotifications()

Airing Service

Access airing schedule information:

// Get airing schedule for today
const airingToday = await client.airing.getAiringSchedules({
    airingAtGreater: Math.floor(Date.now() / 1000),
    airingAtLesser: Math.floor(Date.now() / 1000) + 86400,
    page: 1,
    perPage: 20,
})

// [
//   {
//     id: 33057,
//     airingAt: 1412508600,
//     timeUntilAiring: -330622276,
//     episode: 1,
//     mediaId: 20591,
//     media: {
//       id: 20591,
//       title: [Object ...],
//       coverImage: [Object ...],
//       type: "ANIME",
//       format: "TV",
//       status: "FINISHED",
//       episodes: 12,
//       duration: 23,
//       genres: [ "Drama", "Romance", "Sci-Fi", "Supernatural" ],
//     },
//     ...
//   }
//   ...
// ]

// Get airing schedule for a specific anime
const animeSchedule = await client.airing.getAiringSchedules({
    mediaId: 176496, // Solo Leveling Season 2 -Arise from the Shadow-
    page: 1,
    perPage: 20,
})

// [
//   {
//     id: 390734,
//     airingAt: 1736002800,
//     timeUntilAiring: -7128211,
//     episode: 1,
//     mediaId: 176496,
//     media: {
//       id: 176496,
//       title: [Object ...],
//       coverImage: [Object ...],
//       type: "ANIME",
//       format: "TV",
//       status: "RELEASING",
//       episodes: 13,
//       duration: 24,
//       genres: [ "Action", "Adventure", "Fantasy" ],
//     },
//   }, {
//     id: 390735,
//     airingAt: 1736607600,
//     timeUntilAiring: -6523411,
//     episode: 2,
//     mediaId: 176496,
//     media: {
//       id: 176496,
//       title: [Object ...],
//       coverImage: [Object ...],
//       type: "ANIME",
//       format: "TV",
//       status: "RELEASING",
//       episodes: 13,
//       duration: 24,
//       genres: [ "Action", "Adventure", "Fantasy" ],
//     },
//   }
// ...
// ]

Recommendation Service

Access media recommendations:

// Get recommendations for a media
const recommendations = await client.recommendation.getRecommendations({
    mediaId: 1,
    page: 1,
    perPage: 20,
})

// {
//   pageInfo: {
//     total: 5000,
//     perPage: 20,
//     currentPage: 1,
//     lastPage: 250,
//     hasNextPage: true,
//   },
//   nodes: [
//     {
//       id: 250,
//       rating: 588,
//       userRating: "NO_RATING",
//       media: [Object ...],
//       mediaRecommendation: [Object ...],
//       user: [Object ...],
//     }, {
//       id: 252,
//       rating: 14,
//       userRating: "NO_RATING",
//       media: [Object ...],
//       mediaRecommendation: [Object ...],
//       user: [Object ...],
//     }
//     ...
//   ]
// }

Review Service

Access user reviews:

// Get reviews for a specific media
const mediaReviews = await client.reviews.getReviews({
    mediaId: 1,
})

📄 Pagination

Most list endpoints support pagination. You can specify the page and perPage parameters:

// Get the second page of results with 10 items per page
const results = await client.media.search({
    search: 'anime',
    page: 2,
    perPage: 10,
})

// Access pagination information
console.log(`Total: ${results.pageInfo.total}`)
console.log(`Current page: ${results.pageInfo.currentPage}`)
console.log(`Last page: ${results.pageInfo.lastPage}`)
console.log(`Has next page: ${results.pageInfo.hasNextPage}`)

// Total: 5000
// Current page: 2
// Last page: 500
// Has next page: true

📝 Examples

Want to see more examples? 👉 Check out the examples

🤝 Contributing

Want to get involved? Check out our contribution guide for everything you need to know.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.