Metacritic Scores Scraper avatar

Metacritic Scores Scraper

Pricing

from $1.26 / 1,000 results

Go to Apify Store
Metacritic Scores Scraper

Metacritic Scores Scraper

Critic and user scores for games, movies and TV from Metacritic's own JSON API. Paginates by offset because Metacritic's `page` parameter is inert — every value returns the same 24 rows — and keeps the 0-100 critic score and the 0-10 user score clearly apart.

Pricing

from $1.26 / 1,000 results

Rating

0.0

(0)

Developer

Ibnu Adzim

Ibnu Adzim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Critic and user scores for games, movies and TV from Metacritic's own internal JSON API, plus full title detail from JSON-LD. HTTP-only, no API key, no login, no browser.

Modes

ModeWhat you get
browseThe catalogue, sorted and filtered — Metascore, user score, sentiment breakdown, genres, release date. Games (14,335), movies (17,317) and TV (3,444).
titlesFull detail for titles you name — cast, director/creator, publisher, platforms, images, trailer, description.

Five upstream quirks it corrects

1. The parameter called page does nothing

Holding everything else constant:

page=1, 2, 3, 100, 600, 5000 -> the IDENTICAL 24 items, every time
24/24 overlapping page 1, same first title,
HTTP 200, plausible data
offset=0, 24, 48, 240 -> 24 items each, ZERO overlap

This is worse than a clamp. A clamp eventually stops; page looks like it is working forever. A walker built on it collects the same 24 rows over and over and reports thousands of results — all duplicates — with no error and no empty page to stop on.

The API tells on itself if you read links.next.href: its own "next" link keeps page=1 and appends &offset=24. This actor paginates by offset, never sends page, and publishes offsetsWalked instead of page numbers so the walk is auditable.

2. The two scores are on different scales, and only one says so

criticScoreSummary: {"score": 99, "max": 100, "reviewCount": 22, ...}
userScore: {"score": 9.1} <- no `max` field anywhere

The critic score is 0–100 and declares its maximum. The user score is 0–10 and declares nothing. Publishing both under a field called "score" invites a tenfold comparison error, so they are named apart (criticScore / criticScoreMax, userScore / userScoreMax) and every row carries scoresUseDifferentScales: true.

3. The sentiment buckets are not a partition of the review count

Measured across 48 games, 7 disagreed — and every one undercounted:

Titlepositive + neutral + negativereviewCountshortfall
Zelda: Breath of the Wild1091178
Red Dead Redemption 29910910
Super Mario Odyssey11412410
Elden Ring86937

Never the other direction, and it clusters on the most-reviewed titles — some reviews are counted in the total but assigned to no sentiment bucket. Both figures ship, plus criticSentimentBucketSum, criticReviewsUnbucketed and criticSentimentBucketsCoverAllReviews, rather than implying the buckets add up.

4. An unknown productType silently returns games

SentAnswer
productType=nosuchtype200 with the games catalogue, 14,335 results
sortBy=-nosuchfieldHTTP 400 — honest
genres=nosuchgenre-xyz200 with totalResults: 0 — honest
nosuchparam=x200, ignored

So a typo in the product type answers a different question convincingly. It is validated locally and refused before a request is spent. sortBy is validated too — upstream is honest there, but failing early costs nothing.

5. totalResults is true, and the walk ends honestly

Rare enough in this portfolio to state plainly. Games claims 14,335:

offset 14,300 -> 24 rows offset 14,328 -> exactly 7 rows (14,328+7 = 14,335)
offset 14,400 -> 0 rows offset 100,000 -> 0 rows

No wrap back to the start, no clamp to the last page, no phantom results.

Bonus: the apiKey is decorative

The same query returns identical data with the correct key, a bogus key, or no key at all. It is embedded in the site's own HTML anyway. This actor never sends one and never caches one — there is nothing to rot.

Output

One SEARCH_SUMMARY per run, one TITLE per title, one ERROR per failure.

TITLE rows carry the upstream object verbatim plus titleSlug, titleUrl, titleName, metacriticId, productType, itemType, releaseDate, premiereYear, contentRating, genres, description, criticScore, criticScoreMax, criticReviewCount, the sentiment breakdown and its shortfall fields, userScore, userScoreMax, resultOffset and resultRank. With detail: cast, directors, creators, publishers, productionCompanies, gamePlatforms, imageUrl, trailerUrl, schemaType.

Limits

  • The URL segment differs from the API's productType — game vs games, movie vs movies. A wrong segment is an honest 404. Pass a full metacritic.com URL in titles mode and the segment is taken from it.
  • Page size is fixed at 24: limit above that is an honest HTTP 400.
  • Music is not covered — that section serves no JSON-LD and no __NUXT__ payload.
  • There is no WAF on this host; a proxy is offered but was not needed for any of the reconnaissance.