Skip to content
javinfo

Analytics API

Performer stats, output candles, co-stars, leaderboard and weekly market volume.

/analytics turns the catalog into numbers: output, rating and studio spread, co-stars, a leaderboard, weekly market volume. All from release dates, javlibrary ratings and facet counts we already hold. No view counts, no invented series.

Six keyed GET endpoints. Price starts at $0.60 per 1,000 calls; leaderboard and co-star graph cost more as num grows.

Performer id

Four endpoints take q: stats, output candles, timeline, co-stars. q is an id from /idols, a javdatabase slug like yua-mikami or a DMM-only dmm-1005467.

q is a document lookup, not a search. A Japanese name such as 三上悠亜 returns 404: it matches neither names nor aliases. Search /idols first, pass the id:

curl -s -X POST https://api.javinfo.dev/idols \
  -H "x-javinfo-key: $KEY" -H 'content-type: application/json' \
  -d '{ "q": "yua" }'

Stats — /analytics/idols/stats

The profile card in one call: output, span, rating, genre and studio spread, a 0–1 star score. For a performer header or shortlist ranking.

ParameterTypeRequiredNotes
qstringyesid or slug from /idols
curl -s 'https://api.javinfo.dev/analytics/idols/stats?q=yua-mikami' \
  -H "x-javinfo-key: jvi_your_key_here"

Response 200 (lists trimmed):

{
  "idol": {
    "id": "yua-mikami",
    "name": "Yua Mikami",
    "nameJa": "三上悠亜",
    "image": "https://pics.dmm.co.jp/mono/actjpgs/mikami_yua.jpg",
    "tags": [
      "Twenties",
      "Big Tits"
    ],
    "age": 33,
    "heightCm": 159,
    "cup": "G",
    "debut": null,
    "birthplace": "Aichi",
    "aliases": [
      "みかみゆあ"
    ]
  },
  "works": 1127,
  "worksBySource": {
    "fanza": 1127,
    "javdatabase": 365,
    "javlibrary": 457,
    "javbus": 417,
    "missav": 358
  },
  "firstRelease": "2015-06-01",
  "lastRelease": "2026-11-20",
  "releasesLast90": 30,
  "avgRating": 8.02,
  "ratedTitles": 168,
  "studioCount": 8,
  "topGenres": [
    {
      "genre": "Big Tits",
      "count": 765
    },
    {
      "genre": "Over 4 Hours",
      "count": 610
    },
    "…"
  ],
  "topStudios": [
    {
      "studio": "S1 NO.1 STYLE",
      "count": 991
    },
    {
      "studio": "ROOKIE",
      "count": 48
    },
    "…"
  ],
  "cadenceDays": 115,
  "starPower": 0.885,
  "starPower100": 88,
  "asOf": "2026-11-08T07:34:17.700Z"
}

works is the largest single-source count, not a sum. The same title sits in fanza, javdatabase, javlibrary, javbus and missav, so adding them inflates it fourfold. worksBySource exposes the overlap; counts never sum to works.

avgRating is javlibrary's 1–10 average over up to 200 rated titles; ratedTitles counts the ratings behind it.

studioCount, topGenres and topStudios count deduplicated titles, never summed across sources, so none exceeds works. Yua Mikami: works 1127, studioCount 8, top genre "Big Tits" 765 titles, top studio "S1 NO.1 STYLE" 991.

cadenceDays is the longest gap in days between consecutive releases, not an average. starPower blends volume, rating, last-90-day output, studio spread, career length and recency on a 0–1 scale; starPower100 puts the same number on a 0–100 scale.

A miss returns 404:

curl -s 'https://api.javinfo.dev/analytics/idols/stats?q=nobody-zzzz-qq' \
  -H "x-javinfo-key: jvi_your_key_here"
{
  "defined": false,
  "code": "NOT_FOUND",
  "status": 404,
  "message": "idol not found"
}

Cost: $0.60 per 1,000 calls. Codes: 200, 400, 401, 402, 404, 429. Reference: idolStats.

Candles — /analytics/idols/ohlc

A candlestick series of a performer's career: cumulative release count, bucketed by day, week or month. A flat close means no release in that bucket; a rising one, new output.

Not a price, no view-count history. Release dates are all we can observe, so that is what the candles chart.

ParameterTypeDefaultRange
qstringrequiredid or slug from /idols
bucket"day" | "week" | "month""week"
limitinteger50010–2000

limit caps the candles returned; with more buckets, newest are kept, oldest dropped. A limit under 10 or a bucket other than day, week or month is a 400.

curl -s 'https://api.javinfo.dev/analytics/idols/ohlc?q=yua-mikami&bucket=month&limit=12' \
  -H "x-javinfo-key: jvi_your_key_here"

Response 200. Twelve monthly candles cover the last year; older ones drop (candles and ema trimmed):

{
  "id": "yua-mikami",
  "metric": "cumulative_releases",
  "source": "catalogue",
  "bucket": "month",
  "candles": [
    {
      "t": "2025-12-01",
      "o": 1075,
      "h": 1083,
      "l": 1075,
      "c": 1083,
      "v": 9
    },
    {
      "t": "2026-01-01",
      "o": 1084,
      "h": 1091,
      "l": 1084,
      "c": 1091,
      "v": 8
    },
    "…",
    {
      "t": "2026-11-01",
      "o": 1125,
      "h": 1127,
      "l": 1125,
      "c": 1127,
      "v": 3
    }
  ],
  "changePct": 4.84,
  "ema": [
    1083,
    1085,
    "…"
  ],
  "totalReleases": 1127,
  "truncated": true,
  "asOf": "2026-11-08T07:34:17.117Z"
}

Candle fields:

FieldMeaning
tBucket start, YYYY-MM-DD. A week starts on Monday, a month on the 1st.
oCumulative release count at the first release in the bucket.
hHighest cumulative count reached inside the bucket.
lLowest cumulative count inside the bucket.
cCumulative count at the last release in the bucket.
vNumber of observations in the bucket.

In the catalogue series one observation is one release row, so v counts releases in that bucket. A two-release bucket opens on the count after the first, closes after the second, and reports v: 2.

metric and source say which series you got. Once the snapshot job has at least two days recorded, the endpoint switches to metric: "star_power" and source: "snapshots": candles then measure star score over time, scaled by 1,000, with totalReleases: 0 and truncated: false.

changePct is the change from first open to last close, across returned candles; ema is a 7-period exponential moving average of the closes, the same length as candles.

truncated: true means older candles were dropped to fit limit; newest always stay. totalReleases is the full career count, whatever limit. Raise limit up to 2000 candles for the whole curve.

Cost: $0.60 per 1,000 calls. Codes: 200, 400, 401, 402, 404, 429. Reference: idolOhlc.

Timeline — /analytics/idols/timeline

Monthly release counts plus the four values a profile page needs: debut, latest release, peak month, longest gap. All from release dates.

ParameterTypeRequiredNotes
qstringyesid or slug from /idols
curl -s 'https://api.javinfo.dev/analytics/idols/timeline?q=yua-mikami' \
  -H "x-javinfo-key: jvi_your_key_here"

Response 200 (months trimmed):

{
  "id": "yua-mikami",
  "debut": "2015-06-01",
  "latest": "2026-11-24",
  "peakMonth": "2023-07",
  "longestGapDays": 115,
  "months": [
    { "month": "2015-06", "releases": 2 },
    { "month": "2015-09", "releases": 2 }
  ],
  "truncated": false,
  "asOf": "2026-11-06T18:31:34.750Z"
}

months is ascending YYYY-MM, only months with a release. peakMonth is the busiest; longestGapDays the largest gap between consecutive release dates.

latest comes from its own newest-first query, so it stays exact when truncated is true. That flag means the ascending page hit 10,000 rows; the monthly list then stops short of newest releases.

Cost: $0.60 per 1,000 calls. Codes: 200, 400, 401, 402, 404, 429. Reference: idolTimeline.

Co-stars — /analytics/idols/costars

Collaborators ranked by shared titles. One facet query over the filmography; the performer is excluded.

ParameterTypeDefaultRange
qstringrequiredid or slug from /idols
numinteger151–50
curl -s 'https://api.javinfo.dev/analytics/idols/costars?q=yua-mikami&num=3' \
  -H "x-javinfo-key: jvi_your_key_here"

Response 200 (results trimmed):

{
  "id": "yua-mikami",
  "count": 3,
  "results": [
    { "name": "Aika Yumeno", "sharedTitles": 771 },
    { "name": "Miharu Usa", "sharedTitles": 675 }
  ],
  "asOf": "2026-11-06T18:31:34.119Z"
}

sharedTitles counts titles with both names in the catalog.

Cost: $0.90 per 1,000 calls at num=15. num up to 10 costs $0.60; above that the price scales to $3.00 at num=50. Codes: 200, 400, 401, 402, 404, 429. Reference: idolCostars.

Leaderboard — /analytics/leaderboard

Ranks performers over a window by three metrics.

metricRanks byscore
releasesOutput in the windowThe performer's releases ÷ the leader's releases, 0–1
ratingAdjusted javlibrary average0–1
momentumThe window against the one beforeRatio ÷ 3, capped at 1
ParameterTypeDefaultRange
rangeinteger907–365, a number of days
metric"releases" | "rating" | "momentum""releases"
numinteger201–100
curl -s 'https://api.javinfo.dev/analytics/leaderboard?range=30&metric=releases&num=3' \
  -H "x-javinfo-key: jvi_your_key_here"

Response 200 (results trimmed):

{
  "metric": "releases",
  "range": 30,
  "count": 3,
  "truncated": false,
  "results": [
    {
      "name": "Yui Hatano",
      "nameJa": null,
      "releases": 67,
      "avgRating": null,
      "studios": 10,
      "lastRelease": "2026-11-06",
      "score": 1
    },
    {
      "name": "Yui Tenma",
      "nameJa": null,
      "releases": 55,
      "avgRating": null,
      "studios": 4,
      "lastRelease": "2026-11-06",
      "score": 0.821
    }
  ],
  "asOf": "2026-11-06T18:31:35.824Z"
}

releases is an exact facet count. studios and lastRelease come from the 1,000 newest hits, so they can undercount on a long range.

avgRating is javlibrary's 1–10 average for rated titles, or null when none. rating ranks only performers with any rated title, pulling the average toward a 3.5/5 prior by rated count; one 10/10 cannot top the list.

momentum divides this window's release count by the previous equal-length window. No releases before gives a ratio of 2, scoring 0.667. Ties break on release count.

name is the facet key: Latin when the index has one, Japanese otherwise. nameJa is always null today.

truncated: true means the name facet hit the index's value cap, so counts cover top names, not everyone.

A bad enum is 400; the failing parameter is in data.issues[].path:

curl -s 'https://api.javinfo.dev/analytics/leaderboard?metric=views' \
  -H "x-javinfo-key: jvi_your_key_here"
{
  "defined": false,
  "code": "BAD_REQUEST",
  "status": 400,
  "message": "Input validation failed",
  "data": {
    "issues": [
      {
        "code": "invalid_value",
        "values": ["releases", "rating", "momentum"],
        "path": ["metric"],
        "message": "Invalid option: expected one of \"releases\"|\"rating\"|\"momentum\""
      }
    ]
  }
}

The same shape covers every other analytics parameter: an out-of-range range, a num above 100, a bad bucket. The issue names the parameter.

Cost: $1.20 per 1,000 calls at num=20. num up to 10 costs $0.60; above that the price scales to $6.00 at num=100. Codes: 200, 400, 401, 402, 429. Reference: leaderboard.

Market — /analytics/market

Weekly release volume across the DMM + FANZA catalog, plus genres gaining and losing over the window. For a homepage chart or a "what is moving" panel.

ParameterTypeDefaultRange
weeksinteger122–52
moversinteger101–50
curl -s 'https://api.javinfo.dev/analytics/market?weeks=4&movers=3' \
  -H "x-javinfo-key: jvi_your_key_here"

Response 200 (trimmed):

{
  "weeks": 4,
  "volume": [
    { "week": "2026-10-09", "releases": 1319 },
    { "week": "2026-10-16", "releases": 1421 }
  ],
  "totalReleases": 5740,
  "changePct": 1,
  "truncated": false,
  "genres": {
    "gainers": [
      { "genre": "Knee-High Socks", "changePct": 700, "current": 8, "previous": 1 },
      { "genre": "Widow", "changePct": 700, "current": 16, "previous": 2 }
    ],
    "losers": [
      { "genre": "Female Soldier", "changePct": -100, "current": 0, "previous": 19 },
      { "genre": "Fisting", "changePct": -100, "current": 0, "previous": 5 }
    ]
  },
  "asOf": "2026-11-06T18:31:37.397Z"
}

volume has one entry per 7-day window, oldest first; week is the start date. These roll back from today, not calendar weeks.

weeks sets the window count; totalReleases is their sum. changePct compares newest with oldest, one decimal.

genres compares the latest floor(weeks ÷ 2) weeks with the preceding span. Genres under 5 releases in both spans are skipped; small genres add no noise. changePct is current against previous; none before shows 100. gainers and losers are cut to movers.

truncated: true means the genre facet hit its value cap, so lists cover top genres only.

Cost: $0.60 per 1,000 calls. weeks and movers do not change the price. Codes: 200, 400, 401, 402, 429. Reference: market.

Cost

EndpointDefault pagePer 1,000 calls
/analytics/idols/stats$0.60
/analytics/idols/ohlclimit=500$0.60
/analytics/idols/timeline$0.60
/analytics/idols/costarsnum=15$0.90
/analytics/leaderboardnum=20$1.20
/analytics/market$0.60

Size on other endpoints does not affect price: limit, weeks and movers are free to raise.

Only a fresh 200 is charged; cache hits, errors and degraded answers are free. Responses cache 30 to 60 minutes; a repeat inside is a hit. See rate limits and billing.

Common errors

401 no key. The key gate passes it; the handler refuses:

curl -s 'https://api.javinfo.dev/analytics/leaderboard'
{
  "defined": false,
  "code": "UNAUTHORIZED",
  "status": 401,
  "message": "Unauthorized"
}

401 bad key. Rejected earlier by the key gate, with a shorter body:

curl -s 'https://api.javinfo.dev/analytics/leaderboard' \
  -H "x-javinfo-key: jvi_not_a_real_key"
{ "error": "invalid api key" }

Same status, two bodies. Branch on the status code, not code.

402 not enough credit. Nothing is charged. Retry-After: 3600 is advisory; a top-up unblocks immediately:

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

429 over the per-minute cap. Applied before the handler, with Retry-After in seconds:

{ "error": "rate limit exceeded" }

The cap is per account, not per key. See rate limits.

On this page