The AniPub API provides programmatic access to anime metadata, streaming sources, character information, and MyAnimeList-integrated data. All endpoints are publicly accessible over HTTPS — no API key or authentication needed.
ImagePath or Cover field does not start with https://, prepend https://anipub.xyz/ to construct the full URL.
No authentication is required. All endpoints are open and do not require API keys, OAuth tokens, or any headers beyond standard HTTP.
| Status | Meaning | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 400 | Bad Request | Missing or invalid parameters |
| 404 | Not Found | Anime with given ID not found |
| 500 | Server Error | Internal server issue |
Returns metadata for a specific anime by its integer ID. IDs start from 1 and go up to the total count returned by /api/getAll.
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | integer | Required | Anime ID — must be ≥ 1 |
const fetch = require('node-fetch'); // or use built-in fetch (Node 18+) async function getAnimeInfo(id) { const response = await fetch(`https://www.anipub.xyz/api/info/${id}`); if (!response.ok) { throw new Error(`HTTP error: ${response.status}`); } const data = await response.json(); // Resolve relative image paths const resolveImg = path => path.startsWith('https://') ? path : `https://anipub.xyz/${path}`; data.ImagePath = resolveImg(data.ImagePath); data.Cover = resolveImg(data.Cover); return data; } getAnimeInfo(1).then(console.log).catch(console.error);
import requests def get_anime_info(anime_id: int) -> dict: url = f"https://www.anipub.xyz/api/info/{anime_id}" response = requests.get(url) response.raise_for_status() data = response.json() # Resolve relative image paths def resolve_img(path): return path if path.startswith("https://") else f"https://anipub.xyz/{path}" data["ImagePath"] = resolve_img(data["ImagePath"]) data["Cover"] = resolve_img(data["Cover"]) return data anime = get_anime_info(1) print(anime["Name"], anime["MALScore"])
<?php function getAnimeInfo($id) { $url = "https://www.anipub.xyz/api/info/" . intval($id); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $body = curl_exec($ch); curl_close($ch); $data = json_decode($body, true); // Resolve relative image paths foreach (['ImagePath', 'Cover'] as $key) { if (!str_starts_with($data[$key], 'https://')) { $data[$key] = 'https://anipub.xyz/' . $data[$key]; } } return $data; } $anime = getAnimeInfo(1); echo $anime['Name'] . ' — Score: ' . $anime['MALScore']; ?>
# Get anime info for ID 1 curl -X GET "https://www.anipub.xyz/api/info/1" \ -H "Accept: application/json" # Pretty print with jq curl -s "https://www.anipub.xyz/api/info/1" | jq '.' # Extract just name and score curl -s "https://www.anipub.xyz/api/info/1" | \ jq '{name: .Name, score: .MALScore, genres: .Genres}'
package main import ( "encoding/json" "fmt" "net/http" "strings" ) type AnimeInfo struct { ID int `json:"_id"` Name string `json:"Name"` ImagePath string `json:"ImagePath"` Cover string `json:"Cover"` MALScore string `json:"MALScore"` Genres []string `json:"Genres"` Status string `json:"Status"` } func resolveImg(path string) string { if strings.HasPrefix(path, "https://") { return path } return "https://anipub.xyz/" + path } func getAnimeInfo(id int) (AnimeInfo, error) { url := fmt.Sprintf("https://www.anipub.xyz/api/info/%d", id) resp, err := http.Get(url) if err != nil { return AnimeInfo{}, err } defer resp.Body.Close() var anime AnimeInfo json.NewDecoder(resp.Body).Decode(&anime) anime.ImagePath = resolveImg(anime.ImagePath) anime.Cover = resolveImg(anime.Cover) return anime, nil }
require 'net/http' require 'json' require 'uri' def get_anime_info(id) uri = URI.parse("https://www.anipub.xyz/api/info/#{id}") resp = Net::HTTP.get_response(uri) data = JSON.parse(resp.body) # Resolve relative image paths ['ImagePath', 'Cover'].each do |key| data[key] = "https://anipub.xyz/#{data[key]}" unless data[key].start_with?('https://') end data end anime = get_anime_info(1) puts "#{anime['Name']} — MAL Score: #{anime['MALScore']}"
▶ GET /api/info/:id
{
"_id": 1,
"Name": "Onmyou Kaiten Re:Birth",
"ImagePath": "onmyou-kaiten-rebirth.webp", // → prepend https://anipub.xyz/ if no https://
"Cover": "onmyou-kaiten-rebirth1.webp",
"Synonyms": "Onmyou Kaiten Re:verse",
"Aired": "Jul 3, 2025 to ?",
"Premiered": "Summer 2025",
"RatingsNum": 35,
"Genres": ["action", "fantasy"],
"Studios": "Aniplex, Shueisha, ufotable, Aniplex of America",
"Producers": "David Production",
"DescripTion": "Onmyo Kaiten Re : Birth Verse anime...",
"Duration": "23m",
"MALScore": "6.8",
"Status": "Ongoing",
"epCount": 5
}
Returns an integer representing the total number of anime entries currently in the database. Use this to know the valid ID range for other endpoints.
const res = await fetch('https://www.anipub.xyz/api/getAll'); const total = await res.json(); // e.g. 1030 console.log(`Database has ${total} anime entries`); console.log(`Valid IDs: 1 → ${total}`);
import requests total = requests.get("https://www.anipub.xyz/api/getAll").json() print(f"Total anime: {total} | Valid IDs: 1 to {total}")
curl -s "https://www.anipub.xyz/api/getAll" # Returns: 1030
$total = json_decode(file_get_contents('https://www.anipub.xyz/api/getAll')); echo "Total: $total | Valid IDs: 1–$total";
▶ GET /api/getAll
1030
Returns iframe streaming links for a specific anime including per-episode links. The link field contains src=https://... suitable for iframe embeds. Note: the _id field may now be a MongoDB ObjectId string.
_id field is deprecated as an integer. It may be a MongoDB ObjectId string like "68971dc4e9396134d130f8e8". Use the URL parameter :id as the authoritative identifier.
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | integer | Required | Anime ID (1 to getAll value) |
async function getStreamLinks(id) { const res = await fetch(`https://www.anipub.xyz/v1/api/details/${id}`); const data = await res.json(); const { local } = data; // Convert "src=URL" → iframe-ready string const toIframeSrc = link => link.replace('src=', ''); const mainLink = toIframeSrc(local.link); const epLinks = local.ep.map((e, i) => ({ episode: i + 1, src: toIframeSrc(e.link) })); return { mainLink, epLinks, name: local.name }; } getStreamLinks(119).then(d => { console.log(`Anime: ${d.name}`); d.epLinks.forEach(e => console.log(`EP ${e.episode}: ${e.src}`)); });
import requests data = requests.get("https://www.anipub.xyz/v1/api/details/119").json() local = data["local"] print(f"Anime: {local['name']}") for i, ep in enumerate(local["ep"], 1): src = ep["link"].replace("src=", "") print(f"Episode {i}: {src}")
curl -s "https://www.anipub.xyz/v1/api/details/119" | jq '.local.ep[].link'
$data = json_decode(file_get_contents('https://www.anipub.xyz/v1/api/details/119'), true); $local = $data['local']; foreach ($local['ep'] as $i => $ep) { $src = str_replace('src=', '', $ep['link']); echo "EP " . ($i+1) . ": $src\n"; }
▶ GET /v1/api/details/:id
Returns the most comprehensive dataset: local anime info, full MyAnimeList data via Jikan API integration, and character list with voice actors. Best endpoint for rich anime pages.
async function getFullDetails(id) { const res = await fetch(`https://www.anipub.xyz/anime/api/details/${id}`); const { local, jikan, characters } = await res.json(); const resolveImg = p => p?.startsWith('https://') ? p : `https://anipub.xyz/${p}`; return { title: local.Name, poster: resolveImg(local.ImagePath), cover: resolveImg(local.Cover), score: local.MALScore, genres: local.Genres, malData: jikan, trailer: jikan.trailer?.embed_url, cast: characters.map(c => ({ name: c.character.name, role: c.role, image: c.character.images.webp.image_url, vas: c.voice_actors })) }; } getFullDetails(119).then(d => { console.log(`${d.title} — ${d.cast.length} characters`); });
import requests data = requests.get("https://www.anipub.xyz/anime/api/details/119").json() local = data["local"] jikan = data["jikan"] characters = data["characters"] print(f"Title: {local['Name']}") print(f"MAL Score: {local['MALScore']}") print(f"Synopsis: {jikan['synopsis'][:200]}...") print("\nMain Cast:") for char in characters: print(f" {{char['character']['name']}} ({{char['role']}})")
# Full details curl -s "https://www.anipub.xyz/anime/api/details/119" | jq '.' # Just characters curl -s "https://www.anipub.xyz/anime/api/details/119" | \ jq '.characters[] | {name: .character.name, role}' # Local + MAL score comparison curl -s "https://www.anipub.xyz/anime/api/details/119" | \ jq '{local_score: .local.MALScore, mal_score: .jikan.score}'
$data = json_decode(file_get_contents('https://www.anipub.xyz/anime/api/details/119'), true); $local = $data['local']; $characters = $data['characters']; foreach ($characters as $char) { echo $char['character']['name'] . ' — ' . $char['role'] . "\n"; }
resp, _ := http.Get("https://www.anipub.xyz/anime/api/details/119") defer resp.Body.Close() var result struct { Local struct{ Name string `json:"Name"` } `json:"local"` Characters []struct{ Character struct{ Name string `json:"name"` } `json:"character"` Role string `json:"role"` } `json:"characters"` } json.NewDecoder(resp.Body).Decode(&result) fmt.Println(result.Local.Name)
▶ GET /anime/api/details/:id
Checks if a given anime name and genre combination exists in the database. Pass the anime name and one or more genres; the API returns match data.
| Body Field | Type | Required | Description |
|---|---|---|---|
| Name | string | Required | Name of the anime to search for |
| Genre | string | array | Required | Genre string or array of genre strings. e.g. 'Action' or ['Action','Drama'] |
const checkAnime = async (name, genre) => { const res = await fetch("https://anipub.xyz/api/check", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ Name: name, Genre: genre }) }); return res.json(); }; // Single genre await checkAnime("Jujutsu Kaisen", "Action"); // Multiple genres await checkAnime("Jujutsu Kaisen", ["Action", "Drama"]);
import requests payload = { "Name": "Jujutsu Kaisen", "Genre": ["Action", "Drama"] # or "Action" as a string } res = requests.post( "https://anipub.xyz/api/check", json=payload ) print(res.json())
# Single genre curl -X POST "https://anipub.xyz/api/check" \ -H "Content-Type: application/json" \ -d '{"Name":"Jujutsu Kaisen","Genre":"Action"}' # Array of genres curl -X POST "https://anipub.xyz/api/check" \ -H "Content-Type: application/json" \ -d '{"Name":"Jujutsu Kaisen","Genre":["Action","Drama"]}'
$payload = json_encode([ 'Name' => 'Jujutsu Kaisen', 'Genre' => ['Action', 'Drama'] ]); $ch = curl_init('https://anipub.xyz/api/check'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], ]); $result = json_decode(curl_exec($ch), true); var_dump($result);
import axios from 'axios'; const { data } = await axios.post('https://anipub.xyz/api/check', { Name: 'Jujutsu Kaisen', Genre: ['Action', 'Drama'] }); console.log('Name match:', data.nameMatch); console.log('Genre match:', data.genreMatch);
▶ POST /api/check
Build and send any request to the AniPub API directly from here. Mix and match endpoints and IDs.