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

node-hitomi

v9.1.1

Published

Hitomi.la API for Node.js

Readme

banner

Hitomi.la API for Node.js

Would you call me a gentleman?

npm version npm type definition license

Installation

[!IMPORTANT]

Due to frequent changes on Hitomi.la, it is highly recommended to use the latest version.

Node.js 10.20 or newer is required.

npm install node-hitomi
yarn add node-hitomi
pnpm add node-hitomi
bun add node-hitomi

Features

  • Gallery Search: Filter by tags and title, choose sort order, and paginate results.
  • Gallery Retrieval: Load full gallery metadata, including title, type, language, artists, and relations.
  • Tag Management: Create, parse, search, and list tags. Also list available languages for a tag.
  • Image Downloads: Resolve URLs and fetch images in AVIF/WebP/JXL (when available), with optional thumbnail sizes.
  • Video Downloads: Fetch gallery videos and poster images.

Usage

The package exports a default client instance, but you can also create your own client for custom configuration.

import { Hitomi } from 'node-hitomi';
import { Agent } from 'https';

const agent = new Agent({
	keepAlive: true,
	// Bypass server name indication field blocking
	servername: '',
	rejectUnauthorized: false
});

const hitomi = new Hitomi({
	agent: agent,
	indexMaximumAge: 300000,
	imageContextMaximumAge: 1800000
});

If you use CommonJS module:

const { hitomi, SortType /* and more... */ } = require('node-hitomi');

Galleries

GalleryManager lets you retrieve individual galleries and list matching gallery references.

GalleryManager.retrieve(id)

Retrieves a full gallery by id and returns a Gallery instance.

import hitomi from 'node-hitomi';

// Retrieve a gallery by id
const gallery = await hitomi.galleries.retrieve(123456);

console.log(`Title: ${gallery.title.display}`);
console.log(`Type: ${gallery.type}`);
console.log(`Language: ${gallery.language?.name}`);

GalleryManager.list(options?)

Lists galleries that match the given criteria. You can pass tags, a title query, sort options, and paging options. The method returns GalleryReference[].

import hitomi, { SortType } from 'node-hitomi';

// Parse a search expression into structured tag objects
const tags = hitomi.tags.parse('male:sole_male -female:netorare series:blue_archive');

// List matching gallery references
const references = await hitomi.galleries.list({
	tags: tags,
	title: 'serina',
	orderBy: SortType.PopularityMonth
});

// Resolve the first reference to a full gallery
if(references.length > 0) {
	const firstGallery = await references[0].retrieve();
	console.log(firstGallery.title.display);
}

[!WARNING]

Not every options.page usage is valid. It must meet the restrictions below.

  • Only one non-language tag is allowed (optionally combined with a language tag).
  • Negative tags and title are not supported.
const simpleTags = hitomi.tags.parse('type:manga language:english');

// List matching gallery references with pagination
const pagedReferences = await hitomi.galleries.list({
	tags: simpleTags,
	orderBy: SortType.DatePublished,
	page: {
		index: 0,
		size: 25
	}
});

console.log(pagedReferences, `(${pagedReferences['length']} galleries)`);

Tags

TagManager helps you create, parse, search, and list tags.

TagManager.create(type, name, isNegative?)

Creates a Tag instance with a type, name, and optional negation flag.

import hitomi from 'node-hitomi';

// Create a series tag and list available languages for that tag
const tag = hitomi.tags.create('series', 'trickcal_revive', false);
const languages = await tag.listLanguages();

console.log(languages);

TagManager.parse(expression)

Parses a human-readable expression into unique Tag instances. The expected format is [-]type:name, where spaces are represented by underscores.

import hitomi from 'node-hitomi';

// Parse a string expression into Tag instances
const parsedTags = hitomi.tags.parse('female:yandere male:sole_male -tag:group');

console.log(parsedTags);

TagManager.search(term)

Searches tags by partial term and returns tuples of [Tag, count], where count is the number of galleries associated with each tag.

import hitomi from 'node-hitomi';

// Search tags and print their gallery counts
const tagAndCounts = await hitomi.tags.search('character:agnes');

for(const [tag, count] of tagAndCounts) {
	console.log(`${String(tag)} (${count} galleries)`);
}

TagManager.list(type, startsWith?)

Lists tags of a specific type, optionally filtered by an initial character.

import hitomi, { NameInitial } from 'node-hitomi';

// List female tags that start with 'a'
const femaleATags = await hitomi.tags.list('female', NameInitial.A);

for(const tag of femaleATags) {
	console.log(String(tag));
}

Media

Image.resolveUrl(extension, thumbnailSize?)

Resolves an image URL in the requested format and optional thumbnail size.

[!WARNING]

Not every extension and thumbnailSize combination is valid. It must meet the restrictions below.

| Thumbnail Size | Extension | Requirement (must be true) | | :------------- | :-------- | :------------------------------- | | (none) | (all) | has{Extension} | | Small | (all) | has{Extension} | | Medium | Avif | hasThumbnail && has{Extension} | | Big | (all) | hasThumbnail && has{Extension} |

import hitomi, { Extension, ThumbnailSize } from 'node-hitomi';

// Retrieve a gallery by id and get thumbnail available images
const gallery = await hitomi.galleries.retrieve(123456);
const thumbnails = gallery.getThumbnails();

// Full-size WebP URL
const imageUrl = await thumbnails[0].resolveUrl(Extension.Webp);
console.log(`Image URL: ${imageUrl}`);

// AVIF medium thumbnail URL
const thumbnailUrl = await thumbnails[1].resolveUrl(Extension.Avif, ThumbnailSize.Medium);
console.log(`Thumbnail URL: ${thumbnailUrl}`);

Image.fetch(extension, thumbnailSize?)

Fetches an image as a Buffer. The same extension and thumbnail constraints as Image.resolveUrl apply.

import hitomi, { Extension, ThumbnailSize } from 'node-hitomi';
import { writeFileSync } from 'fs';

// Retrieve a gallery by id and get thumbnail available images
const gallery = await hitomi.galleries.retrieve(123456);
const thumbnails = gallery.getThumbnails();

// Fetch and save a full-size image
const imageBuffer = await thumbnails[0].fetch(Extension.Webp);
writeFileSync('image.webp', imageBuffer);

// Fetch and save a medium thumbnail
const thumbnailBuffer = await thumbnails[1].fetch(Extension.Avif, ThumbnailSize.Medium);
writeFileSync('thumbnail.avif', thumbnailBuffer);

Video.fetch()

Fetches a gallery video as an MP4 Buffer.

import hitomi from 'node-hitomi';
import { writeFileSync } from 'fs';

const gallery = await hitomi.galleries.retrieve(123456);

if(gallery.video) {
	// Fetch and store the MP4 video
	const videoBuffer = await gallery.video.fetch();
	writeFileSync('video.mp4', videoBuffer);
}

Video.fetchPoster()

Fetches the video poster as a WebP Buffer.

import hitomi from 'node-hitomi';
import { writeFileSync } from 'fs';

const gallery = await hitomi.galleries.retrieve(123456);

if(gallery.video) {
	// Fetch and store the WebP poster image
	const posterBuffer = await gallery.video.fetchPoster();
	writeFileSync('poster.webp', posterBuffer);
}

Contribution

Contributions are welcome. Feel free to open an issue for bugs or submit a pull request with improvements.

License

This project is licensed under the MIT License.