{"id":19493490,"url":"https://github.com/zekfad/nhentai-api","last_synced_at":"2025-04-25T20:31:17.178Z","repository":{"id":44952986,"uuid":"213716544","full_name":"Zekfad/nhentai-api","owner":"Zekfad","description":"Node.JS client for nhentai.net undocumented API.","archived":false,"fork":false,"pushed_at":"2023-05-06T23:32:57.000Z","size":1162,"stargazers_count":44,"open_issues_count":13,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-31T20:38:04.797Z","etag":null,"topics":["api","api-client","doujin","javascript","js","nhentai","nhentai-api","node-module","nodejs"],"latest_commit_sha":null,"homepage":"https://zekfad.github.io/nhentai-api/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Zekfad.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-08T18:09:23.000Z","updated_at":"2025-02-18T18:24:29.000Z","dependencies_parsed_at":"2024-06-18T17:22:20.960Z","dependency_job_id":null,"html_url":"https://github.com/Zekfad/nhentai-api","commit_stats":{"total_commits":83,"total_committers":3,"mean_commits":"27.666666666666668","dds":"0.048192771084337394","last_synced_commit":"64cde9538f7d4f6e80c5b10cba92a0f8e0898e05"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zekfad%2Fnhentai-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zekfad%2Fnhentai-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zekfad%2Fnhentai-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zekfad%2Fnhentai-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Zekfad","download_url":"https://codeload.github.com/Zekfad/nhentai-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250890360,"owners_count":21503482,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","api-client","doujin","javascript","js","nhentai","nhentai-api","node-module","nodejs"],"created_at":"2024-11-10T21:26:11.119Z","updated_at":"2025-04-25T20:31:16.839Z","avatar_url":"https://github.com/Zekfad.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Node.JS client for nhentai.net undocumented APIs.\r\n\r\n[![npm version](https://img.shields.io/npm/v/nhentai-api?style=for-the-badge)](https://www.npmjs.com/package/nhentai-api)![node version](https://img.shields.io/node/v/nhentai-api?style=for-the-badge)[![Build status - Linux/OSX](https://img.shields.io/travis/Zekfad/nhentai-api?style=for-the-badge\u0026logo=linux\u0026logoColor=white)](https://travis-ci.org/github/Zekfad/nhentai-api)[![Build status - Windows](https://img.shields.io/appveyor/build/Zekfad/nhentai-api?style=for-the-badge\u0026logo=windows\u0026logoColor=white)](https://ci.appveyor.com/project/Zekfad/nhentai-api)[![Codecov](https://img.shields.io/codecov/c/gh/Zekfad/nhentai-api?style=for-the-badge)](https://codecov.io/gh/Zekfad/nhentai-api)\r\n\r\n\r\nNode.JS module for handling nhentai.net API.\r\n\r\n## Features\r\n\r\n* Objective-oriented API abstraction.\r\n* Bidirectional inspecting (get image from book/get book from image).\r\n* Easy proxy support by using custom Agent (like [this one](https://www.npmjs.com/package/https-proxy-agent)).\r\n* Return URLs for binary data (images).\r\n\r\n## Install\r\n\r\nInstall via yarn:\r\n\r\n```\r\nyarn add nhentai-api\r\n```\r\n\r\nInstall via npm:\r\n\r\n```\r\nnpm i nhentai-api\r\n```\r\n\r\n## Docs\r\n\r\n[Read the docs on GitHub pages.](https://zekfad.github.io/nhentai-api/)\r\n\r\n## Example\r\n\r\n### Import\r\n\r\n#### CommonJS\r\n\r\n```js\r\nconst { API, TagTypes, } = require('nhentai-api');\r\n```\r\n\r\n#### ES6\r\n\r\n```js\r\nimport { API, TagTypes, } from 'nhentai-api';\r\n```\r\n\r\n### Use\r\n\r\n#### Initialize API client\r\n\r\n```js\r\nconst api = new API();\r\n```\r\n\r\n#### Get the book\r\n\r\n```js\r\napi.getBook(177013).then(book =\u003e {\r\n\tapi.getImageURL(book.cover);    // https://t.nhentai.net/galleries/987560/cover.jpg\r\n\tapi.getImageURL(book.pages[1]); // https://i.nhentai.net/galleries/987560/2.jpg\r\n});\r\n```\r\n\r\n#### Get random book\r\n```js\r\nawait api.getRandomBook(); // Book instance\r\n````\r\n\r\n#### Search for the books\r\n\r\n```js\r\napi.search('test').then(async search =\u003e {\r\n\tconsole.log(search); /*\r\n\tSearch {\r\n\t\tapi: API { hosts: [Object], ssl: true, agent: [Agent] },\r\n\t\tquery: 'test',\r\n\t\tpage: 1,\r\n\t\tperPage: 25,\r\n\t\tbooks: [\r\n\t\t\t[Book], [Book], [Book], [Book],\r\n\t\t\t[Book], [Book], [Book], [Book],\r\n\t\t\t[Book], [Book], [Book], [Book],\r\n\t\t\t[Book], [Book], [Book], [Book],\r\n\t\t\t[Book], [Book], [Book], [Book],\r\n\t\t\t[Book], [Book], [Book], [Book],\r\n\t\t\t[Book]\r\n\t\t],\r\n\t\tpages: 67\r\n\t} */\r\n\tsearch = await search.getNextPage(); // Same as api.search('text', 2);\r\n\tconsole.log(search); /*\r\n\tSearch {\r\n\t\t// Same as above\r\n\t\tpage: 2,\r\n\t\t// Same as above\r\n\t\tbooks: [\r\n\t\t\t// Books from 2nd page of search\r\n\t\t],\r\n\t\t// Same as above\r\n\t} */\r\n});\r\n```\r\n\r\nIn case you need to change API implementation (e.g. change proxy) you can pass `api` to\r\n```js\r\nsearch.getNextPage(api);\r\n```\r\n\r\nYou can also use async generator:\r\n```js\r\n// Get first 2 pages\r\nfor await (const search of api.searchGenerator('test')) {\r\n\tconsole.log(search);\r\n\tif (search.page \u003e= 2)\r\n\t\tbreak;\r\n}\r\n```\r\n\r\n#### Working with tags\r\n\r\n`book.tags` has type of `TagsArray`, it is just an `Array\u003cTag\u003e` with helper methods.\r\n\r\n```js\r\nconst tag = book.tags[0]; // Tag\r\n```\r\n\r\n##### Get tag id\r\n```js\r\ntag.id;\r\n```\r\n\r\n##### Get tag name (without count)\r\n```js\r\ntag.name;\r\n// or\r\ntag.toString();\r\n```\r\n\r\n##### Get tag name (with count)\r\n```js\r\ntag.toString(true);\r\n```\r\n\r\n##### Get tag type (as string)\r\n```js\r\ntag.type.type;\r\n// or\r\ntag.type.toString();\r\n```\r\n\r\n##### Pre-filtered tags\r\n\r\n```js\r\nbook.pureTags;   // pure tags (with type 'tag')\r\nbook.categories; // category tags\r\nbook.artists;    // artist tags\r\nbook.parodies;   // parody tags\r\nbook.characters; // character tags\r\nbook.groups;     // group tags\r\nbook.languages;  // language tags\r\n```\r\n\r\n##### Filter tags\r\n\r\nGet artists:\r\n```js\r\nbook.artists;\r\n// or\r\nbook.getTagsWith({\r\n\ttype: TagTypes.Artist, // you may also use Tag.types.Artist or Tag.types.get('artist') \r\n}); // TagsArray (subclass of Array\u003cTag\u003e)\r\n// or\r\nbook.getTagsWith({ type: 'artist', }); // TagsArray (subclass of Array\u003cTag\u003e)\r\n```\r\n\r\nGet tag with name `english`:\r\n```js\r\nbook.getTagsWith({ name: 'english', }); // TagsArray (subclass of Array\u003cTag\u003e)\r\n```\r\n\r\nGet categories\r\n```js\r\nbook.categories;\r\n// or\r\nbook.getTagsWith({ type: TagTypes.Category, }); // Recommended\r\n// or\r\nbook.getTagsWith({ type: Tag.types.Category, });\r\n// or\r\nbook.getTagsWith({ type: Tag.types.get('category'), });\r\n// or\r\nbook.getTagsWith({ type: 'category', });\r\n```\r\n\r\n##### Get tags comma separated\r\n\r\nWithout counts:\r\n```js\r\nbook.tags.toNames().join(', ');\r\n// or\r\nbook.tags.join(', ');\r\n```\r\n\r\nWith counts:\r\n```js\r\nbook.tags.toNames(true).join(', ');\r\n// or\r\nbook.tags.map(tag =\u003e tag.toString(true)).join(', ')\r\n```\r\n\r\nGet all artists:\r\n```js\r\n// With counts\r\nbook.artists.toNames(true).join(', ');\r\n// or\r\nbook.getTagsWith({ type: TagTypes.Artist, }).toNames(true).join(', ');\r\n// Without counts\r\nbook.artists.join(', ');\r\n// or\r\nbook.artists.toNames().join(', ');\r\n// or\r\nbook.getTagsWith({ type: TagTypes.Artist, }).join(', ');\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzekfad%2Fnhentai-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzekfad%2Fnhentai-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzekfad%2Fnhentai-api/lists"}