booru.ts - v1.0.1

A TypeScript library for interacting with Booru style image board APIs such as Rule34, Safebooru, Danbooru and Paheal. It gives you one consistent interface for searching posts and autocompleting tags, so you do not have to deal with each site's own API quirks yourself.

npm install booru.ts
import { Safebooru } from 'booru.ts';

const site = new Safebooru();

const posts = await site.search({
tags: ['1girl'],
sort: 'score',
sortOrder: 'desc',
limit: 10,
});

console.log(posts);

Each result is a BooruPost with fields like id, rating, score, tags, mediaType, originalFile, previewFile, sampleFile, owner and source.

Rule34 requires an API key and user id for every request. Get them from your account settings on rule34.xxx.

import { Rule34 } from 'booru.ts';

const site = new Rule34({
apiKey: 'your-api-key',
userId: 'your-user-id',
});

const posts = await site.search({ tags: ['1girl'], limit: 5 });

Danbooru works without credentials, but anonymous searches are limited to 2 tags. Passing a login and API key raises that limit.

import { Danbooru } from 'booru.ts';

const site = new Danbooru();
const authedSite = new Danbooru({ login: 'your-login', apiKey: 'your-api-key' });

const posts = await authedSite.search({ tags: ['1girl', 'solo'], limit: 5 });

Both work without any credentials.

import { Paheal } from 'booru.ts';

const site = new Paheal();
const posts = await site.search({ tags: ['animated'], limit: 5 });

The search method accepts:

  • tags, an array of tags to filter by
  • sort, one of 'score', 'created' or 'random'
  • sortOrder, 'asc' or 'desc'
  • limit, the number of posts to return
  • page, the page number to fetch

Not every site supports every sort mode. Call site.canSortRandomly() to check whether random sorting is available before using it.

Every site supports tag autocomplete:

const results = await site.autocomplete('blue');
// [{ label: 'blue_eyes', value: 'blue_eyes' }, ...]

Wrap any site in a CachedBooruSite to cache search and autocomplete results in memory with node-cache, so repeated identical requests are served from the cache instead of hitting the real site again.

import { CachedBooruSite, Safebooru } from 'booru.ts';

const site = new CachedBooruSite(new Safebooru(), {
searchTtl: 120,
autocompleteTtl: 300,
});

await site.search({ tags: ['1girl'] }); // fetched from Safebooru
await site.search({ tags: ['1girl'] }); // served from the cache

site.clearCache();

MIT