A type-safe TypeScript client for the IGDB API with a fluent query builder, automatic OAuth token handling, retries, and IGDB-friendly rate limiting.
The package is built for the way IGDB is normally used: start with a typed query, shape the fields you want, drop to raw APICalypse only when you need to, and keep your app code readable.
import { IGDBClient, buildImageUrl } from "@api-wrappers/igdb-wrapper";
const client = new IGDBClient({
clientId: process.env.TWITCH_CLIENT_ID!,
clientSecret: process.env.TWITCH_CLIENT_SECRET!,
});
const games = await client.games
.query()
.select((game) => ({
id: game.id,
name: game.name,
rating: game.rating,
cover: {
imageId: game.cover.image_id,
},
}))
.where((game, { or }) =>
or(game.rating.gte(90), game.aggregated_rating.gte(90)),
)
.sort((game) => game.rating, "desc")
.limit(5)
.execute();
for (const game of games) {
const coverUrl = game.cover?.imageId
? buildImageUrl(game.cover.imageId, { size: "cover_big", retina: true })
: null;
console.log(game.name, game.rating, coverUrl);
}- Typed field selection with editor autocomplete for model fields and nested relations.
- Readable filters through
.where(),or(),and(), and typed comparison helpers. - Raw APICalypse escape hatches with
.fields(),.whereRaw(),.apicalypse(), andendpoint.request(). - Every registered IGDB v4 endpoint exposed as a camel-cased
IGDBClientproperty. - Pagination helpers with
.count()and async-generator.paginate(). - Automatic auth, retry, and rate limiting through
@api-wrappers/api-core. - Useful extras for image URLs, tag numbers,
/meta, protobuf, multi-query, and webhooks. - Structured errors so app code can handle auth, validation, rate limit, and not-found cases directly.
npm install @api-wrappers/igdb-wrapper
# or
yarn add @api-wrappers/igdb-wrapper
# or
pnpm add @api-wrappers/igdb-wrapper
# or
bun add @api-wrappers/igdb-wrapperRequirements: Node.js 18+ (uses native
fetch). TypeScript 5+ recommended.
IGDB uses Twitch application credentials. Create an app in the Twitch Developer Console, then set:
TWITCH_CLIENT_ID=your_client_id
TWITCH_CLIENT_SECRET=your_client_secretimport { IGDBClient } from "@api-wrappers/igdb-wrapper";
const client = new IGDBClient({
clientId: process.env.TWITCH_CLIENT_ID!,
clientSecret: process.env.TWITCH_CLIENT_SECRET!,
});
const game = await client.games
.query()
.select((game) => ({
name: game.name,
summary: game.summary,
releaseDate: game.first_release_date,
}))
.where((game) => game.slug.eq("elden-ring"))
.first();
console.log(game?.name);const results = await client.games
.search("zelda")
.select((game) => ({
name: game.name,
slug: game.slug,
rating: game.rating,
}))
.where((game) => game.rating.gte(70))
.limit(10)
.execute();const pageSize = 20;
const page = 2;
const query = client.games
.query()
.select((game) => ({ name: game.name, rating: game.rating }))
.where((game) => game.rating_count.gte(100))
.sort((game) => game.rating, "desc");
const [items, total] = await Promise.all([
query.limit(pageSize).offset(page * pageSize).execute(),
query.count(),
]);const games = await client.games
.query()
.fields("name", "platforms.name", "cover.image_id")
.whereRaw("platforms = {48,6}")
.apicalypse("limit 10;")
.execute();import { buildImageUrl } from "@api-wrappers/igdb-wrapper";
const game = await client.games
.query()
.select((game) => ({
name: game.name,
cover: { imageId: game.cover.image_id },
}))
.where((game) => game.slug.eq("hades"))
.first();
const coverUrl = game?.cover?.imageId
? buildImageUrl(game.cover.imageId, { size: "cover_big", retina: true })
: null;| Guide | Description |
|---|---|
| Getting Started | Installation, credentials, and your first query |
| Querying | Full query builder API: select, where, sort, paginate |
| Examples | Copyable recipes for search, pagination, images, raw requests, and webhooks |
| Endpoints | All IGDB v4 endpoint properties and raw endpoint access |
| Error Handling | All error types and how to handle them |
| Configuration | Retry, rate limiting, and advanced options |
| API Reference | Complete method signatures |
Example source files are also available in examples/.
This project is licensed under the MIT License - see the LICENSE file for details.