Skip to content
javinfo

Resolve API

Normalize any code spelling and get variants, sources, a share card, provenance and streams for one title.

/resolve tells you what a code is and what every source says. /movie returns the first provider that answers; these endpoints query every source and keep the disagreements.

Use them to normalize abp002, ABP-002 or ABP-2, list every source for a title, or get a share card or stream map in one call.

EndpointReturnsPer 1,000 calls
GET /resolveCanonical code, variants, sources, link, inline card$1.20
POST /resolve/batchFound or not found for up to 100 codes$0.40 per started group of 10 unique codes
GET /resolve/compareTwo titles side by side$0.40
GET /resolve/provenanceSource and confidence per field$0.40
GET /resolve/streamsStream, sample and magnet availability$0.40

GET /resolve

Normalizes any spelling to one canonical code and returns everything attached: variants, sources, a link to /movie, a 1200×630 card.

ParameterTypeRequiredMeaning
qstringyesThe code or spelling to resolve. At least 2 characters.
formatpng, jpg or svgnoCard encoding. Defaults to png.
curl -s 'https://api.javinfo.dev/resolve?q=abp002&format=jpg' \
  -H "x-javinfo-key: jvi_your_key_here"
{
  "input": "abp002",
  "code": "ABP-002",
  "shareSlug": "85150B9G60S0M",
  "found": true,
  "variants": ["ABP-002", "ABP002"],          // 7 total
  "contentIdGuess": "118abp00002",
  "sources": ["fanza", "javdatabase"],        // 6 total
  "link": "/movie?q=ABP-002",
  "card": {
    "format": "jpg",
    "mime": "image/jpeg",
    "dataUri": "data:image/jpeg;base64,…"
  }
}

The card is inline in card.dataUri, so responses are large: about 1.1 MB with png (default), 900 KB with svg, 180 KB with jpg. Pick jpg when size matters — a lossy raster about six times smaller than png. The base64 payload is cut in the example; dataUri is a complete data: URI for <img src>.

FieldMeaning
inputThe string you sent, unchanged.
codeThe canonical code.
variantsEvery spelling that keys the same title, most canonical first.
sourcesPublic ids of the sources that list the title.
contentIdGuessDMM content id when the storefront index has it, otherwise null.
linkAPI path for the same title, /movie?q=<code>. Relative to https://api.javinfo.dev; call it with your x-javinfo-key header.
cardThe 1200×630 card as a data URI, or null.
foundtrue on a 200. A miss is a 404.
shareSlugChecksummed slug for the canonical code.

The card shows the code, English title (shortened, or the code when none), up to three cast names and the studio, up to four genre chips, then rating, runtime, release date and magnet count when known. A STREAMABLE badge marks a stream. The jacket sits right over a blurred cover. null if rendering is unavailable; treat it as optional and keep the metadata.

A code that matches nothing is a 404, not an empty card:

{
  "defined": false,
  "code": "NOT_FOUND",
  "status": 404,
  "message": "no title found for \"ZZZZ-99999\""
}

POST /resolve/batch

Checks up to 100 codes in one request: clean a user's list or match your catalog without 100 sequential calls.

Body fieldTypeRequiredMeaning
codesstring arrayyes1 to 100 non-empty strings.
curl -s -X POST 'https://api.javinfo.dev/resolve/batch' \
  -H "x-javinfo-key: jvi_your_key_here" \
  -H 'content-type: application/json' \
  -d '{"codes":["ABP-002","beb001","ZZZZ-99999"]}'
{
  "count": 3,
  "found": 2,
  "results": [
    { "input": "ABP-002", "code": "ABP-002", "found": true },
    { "input": "beb001", "code": "BEB-001", "found": true },
    { "input": "ZZZZ-99999", "code": "ZZZZ-99999", "found": false }
  ]
}

A miss is found: false inside a normal 200, not a 404; code then holds the best canonical guess. count is codes checked after deduplication; found is hits.

Codes are trimmed and deduplicated before counting. "ABP-002" and " ABP-002 " cost one slot and appear once in results. Matching is exact after trimming, so abp-002 and ABP-002 are two slots.

An empty codes array, more than 100 codes, or an empty string is a 400:

{
  "defined": false,
  "code": "BAD_REQUEST",
  "status": 400,
  "message": "Input validation failed",
  "data": {
    "issues": [
      {
        "origin": "array",
        "code": "too_small",
        "minimum": 1,
        "inclusive": true,
        "path": ["codes"],
        "message": "Too small: expected array to have >=1 items"
      }
    ]
  }
}

The same shape covers the other validation failures, with a different issues entry.

GET /resolve/compare

Two titles side by side: each core card, shared fields, a similarity score.

ParameterTypeRequiredMeaning
astringyesFirst code. At least 2 characters.
bstringyesSecond code. At least 2 characters.
curl -s 'https://api.javinfo.dev/resolve/compare?a=SSIS-001&b=ABP-002' \
  -H "x-javinfo-key: jvi_your_key_here"
{
  "a": {
    "input": "SSIS-001",
    "code": "SSIS-001",
    "shareSlug": "AD9MJMSD60R32E",
    "found": true,
    "variants": [
      "SSIS-001",
      "SSIS001",
      "…"
    ],
    "contentIdGuess": "ssis00001",
    "sources": [
      "fanza",
      "javdatabase",
      "javlibrary",
      "javbus",
      "missav",
      "sextb"
    ],
    "link": "/movie?q=SSIS-001"
  },
  "b": {
    "input": "ABP-002",
    "code": "ABP-002",
    "shareSlug": "85150B9G60S0M",
    "found": true,
    "variants": [
      "ABP-002",
      "ABP002",
      "…"
    ],
    "contentIdGuess": "118abp00002",
    "sources": [
      "fanza",
      "javdatabase",
      "javlibrary",
      "javbus",
      "missav",
      "sextb"
    ],
    "link": "/movie?q=ABP-002"
  },
  "shared": {
    "actresses": [],
    "categories": [],
    "maker": null
  },
  "similarity": 0.05
}

Each side has the /resolve core shape, sans card. sources lists every matching source; contentIdGuess is the DMM content id when the storefront index has it — both as on /resolve.

shared holds the case-insensitive intersection of actresses and categories; maker fills only when both titles carry the exact same maker string.

similarity is a 0 to 1 blend, mostly shared actresses (0.34) and categories (0.26), plus the same maker (0.1), runtime (0.06) and release-date proximity (0.06), rounded to 3 decimals. If either code is missing, that side is found: false, shared empty, similarity 0. Never 404.

GET /resolve/provenance

Shows each field's source, how much the API trusts it, and what other sources said.

ParameterTypeRequiredMeaning
qstringyesThe code or spelling to resolve. At least 2 characters.
curl -s 'https://api.javinfo.dev/resolve/provenance?q=ABP-002' \
  -H "x-javinfo-key: jvi_your_key_here"
{
  "code": "ABP-002",
  "found": true,
  "sources": ["fanza", "javbus"],            // 6 total, alphabetical
  "fields": {
    "title": {
      "value": "NEW TOKYO Style 01 - Aikarin",
      "source": "fanza",
      "confidence": 1,
      "candidates": [                        // 6 total, trust order
        { "source": "fanza", "value": "NEW TOKYO Style 01 - Aikarin" },
        { "source": "javdatabase", "value": "NEW TOKYO Style 01 - Aikarin" }
      ]
    },
    "titleJa": {
      "value": "NEW TOKYO流儀 01 あいかりん",
      "source": "javlibrary",
      "confidence": 0.8,
      "candidates": [                        // 4 total
        { "source": "javlibrary", "value": "NEW TOKYO流儀 01 あいかりん" },
        { "source": "javbus", "value": "NEW TOKYO流儀 01 あいかりん" }
      ]
    },
    "rating": {
      "value": 8.1,
      "source": "javlibrary",
      "confidence": 0.8,
      "candidates": [{ "source": "javlibrary", "value": 8.1 }]
    }
    // releaseDate, runtimeMins, maker, label, series, categories,
    // actresses and cover follow the same shape
  },
  "data": {
    "title": "NEW TOKYO Style 01 - Aikarin",
    "titleJa": "NEW TOKYO流儀 01 あいかりん",
    "rating": 8.1
    // the merged value for every field above
  }
}

fields covers title, titleJa, releaseDate, runtimeMins, maker, label, series, categories, actresses, cover and rating.

Scalars go to the highest-weight source; arrays such as categories and actresses are unioned, not replaced. candidates lists every source that offered a value, best first, so disagreements stay visible.

confidence is the winning weight over the best weight in the response: 1 for the top source, lower for the rest. Weights, highest first: storefronts 1, javdatabase 0.85, javlibrary 0.8, javbus 0.7, missav 0.6, sextb 0.55. sources is alphabetical; candidates is trust order.

An unknown code is a 404 with the same body as GET /resolve.

GET /resolve/streams

Returns where to watch or download a title: HLS streams, samples, magnets, subtitles, gallery size.

ParameterTypeRequiredMeaning
qstringyesThe code or spelling to resolve. At least 2 characters.
curl -s 'https://api.javinfo.dev/resolve/streams?q=ABP-002' \
  -H "x-javinfo-key: jvi_your_key_here"
{
  "code": "ABP-002",
  "found": true,
  "playback": "hls",
  "availability": {
    "magnets": 47,
    "stream": true,
    "sample": false,
    "trailer": false,
    "gallery": 0,
    "subtitles": [],
    "uncensored": false,
    "score": 0.7
  },
  "streams": {
    "master": "https://surrit.com/c511196b-b4f8-47bf-a6b0-64ba625fc2a4/playlist.m3u8",
    "variants": [
      "https://surrit.com/c511196b-b4f8-47bf-a6b0-64ba625fc2a4/1280x720/video.m3u8",
      "https://surrit.com/c511196b-b4f8-47bf-a6b0-64ba625fc2a4/842x480/video.m3u8"
    ]
  },
  "sampleUrl": null,
  "galleryCount": 106,
  "sources": ["fanza", "javdatabase"]        // 6 total
}

playback answers in one line: hls with a stream, else magnet with magnets, else sample with only a sample or trailer, else none.

availability adds detail:

FieldMeaning
magnetsDistinct magnet infohashes across every source.
streamAn HLS master is present.
sampleA sample clip or trailer is present.
trailerA trailer specifically.
galleryGallery image count from the source picked for media.
subtitlesSubtitle languages detected in the metadata. zh is the only one tagged today.
uncensoredThe metadata marks the title as uncensored.
score0 to 1 completeness: magnets 0.35, stream 0.35, sample 0.15, gallery 0.1, subtitles 0.05.

streams is {master, variants} with HLS, else null. master is the playlist for a player; variants are per-resolution playlists. sampleUrl is the sample clip when present; galleryCount is the largest across sources.

An unknown code is a 404 with the same body as GET /resolve.

Cost

Only a fresh 200 is charged. Cache hits (X-Cache: HIT), 4xx responses and degraded answers (X-Degraded) are free. Resolve, compare and provenance cache 1 hour; streams 15 minutes. Batch does not cache.

GET /resolve costs $1.20 per 1,000 calls because it renders the card; other resolve endpoints cost $0.40 per 1,000 calls.

Batch bills the codes left after trimming and deduplication, in started groups of 10:

Unique codesPer 1,000 calls
1–10$0.40
11–20$0.80
21–30$1.20
100$4.00

Status codes

EndpointCodes
GET /resolve200, 400, 401, 402, 404, 429
POST /resolve/batch200, 400, 401, 402, 429
GET /resolve/compare200, 400, 401, 402, 429
GET /resolve/provenance200, 400, 401, 402, 404, 429
GET /resolve/streams200, 400, 401, 402, 404, 429

A q under 2 characters, an unknown format, and the batch body failures above are 400.

Common errors

No key and a bad key both give 401, with different bodies.

# No key
curl -s 'https://api.javinfo.dev/resolve?q=ABP-002'
{
  "defined": false,
  "code": "UNAUTHORIZED",
  "status": 401,
  "message": "Unauthorized"
}
# Bad key
curl -s 'https://api.javinfo.dev/resolve?q=ABP-002' \
  -H "x-javinfo-key: jvi_not_a_real_key"
{ "error": "invalid api key" }

402 means the balance is below the call price. Nothing is charged; Retry-After: 3600 hints for automated clients.

{
  "defined": false,
  "code": "PAYMENT_REQUIRED",
  "status": 402,
  "message": "insufficient balance"
}

429 is the per-account per-minute cap; Retry-After gives seconds to wait.

{ "error": "rate limit exceeded" }

Account side: Rate limits & billing and Errors. Generated reference: /docs/api/discovery/resolve.

On this page