Every Studio Ghibli API tutorial points at a dead Heroku app

The Studio Ghibli API was one of the friendliest "learn to fetch" datasets ever published: 22 films, characters, locations, no keys, lovely nested links between everything. Thousands of tutorials, bootcamp exercises, YouTube videos, and README examples open with the same line โ€” and here is what that line does today (verified September 2026):

curl https://ghibliapi.herokuapp.com/films
# โ†’ HTTP 404
# โ†’ <title>No such app</title>   โ† Heroku's error page, not the API's

Heroku shut down its free dynos in November 2022 and the original host never came back. The tutorial you're following isn't wrong โ€” its data source's landlord evicted it.

1. The quick fix: a genuinely good successor exists

Credit where due: the community mirror at ghibliapi.vercel.app is excellent. In our September 2026 checks it answered in ~0.5s, needs no key, sends real CORS headers (browser fetch() works), serves the same five collections (22 films, 57 people, 25 locations, 7 species, 3 vehicles), supports exact-match filters (?director=Hayao Miyazaki โ†’ 9 films) and ?limit= / ?fields= โ€” and it even preserved the original record UUIDs, so the 2baf70d1-โ€ฆ film id hardcoded in a 2019 tutorial still resolves. If all you need is to finish the tutorial, replace the host and carry on:

- https://ghibliapi.herokuapp.com/films
+ https://ghibliapi.vercel.app/films

Where you'll hit its edges (each verified September 2026):

2. Own the dataset: all five collections in one import

The whole dataset is ~90KB of JSON. Pull it once, keep the original UUIDs as a field (import renumbers ids to integers, so we stash the UUID first), and host your own copy โ€” no signup:

for e in films people locations species vehicles; do
  curl -s "https://ghibliapi.vercel.app/$e" > "$e.json"
done

jq -n '{films:     input | map({uuid:.id} + .),
        people:    input | map({uuid:.id} + .),
        locations: input | map({uuid:.id} + .),
        species:   input | map({uuid:.id} + .),
        vehicles:  input | map({uuid:.id} + .)}' \
  films.json people.json locations.json species.json vehicles.json > db.json

curl -s -X POST "https://mockbird.mockbird.workers.dev/api/projects/import?name=ghibli" \
  -H 'content-type: application/json' --data-binary @db.json
# โ†’ {"id":"YOUR_ID","adminKey":"YOUR_ADMIN_KEY",
#    "resources":[{"name":"films","records":22},{"name":"people","records":57},โ€ฆ]}

Every field is kept verbatim โ€” including the nested people/locations URL arrays inside each film (the importer notes them as warnings and stores them untouched), and the image/movie_banner poster URLs, which point at TMDB and still render in your app straight from your copy.

3. What your copy can do that neither host ever could

All of these ran against a live import while writing this guide:

BASE=https://mockbird.mockbird.workers.dev/m/YOUR_ID

curl "$BASE/films?director=Hayao Miyazaki"        # exact match โ€” same 9 films as upstream
curl "$BASE/films?title_like=totoro"              # substring, case-insensitive โ†’ My Neighbor Totoro
curl "$BASE/films?q=witch"                        # full-text across every field โ†’ 5 films
curl "$BASE/films?sortBy=rt_score&order=desc"     # numeric-aware even on "97"-style strings
curl "$BASE/films?rt_score_gte=97&select=title,rt_score"
#   โ†’ Grave of the Fireflies 97 ยท Only Yesterday 100 ยท Spirited Away 97 ยท Princess Kaguya 100
curl "$BASE/films?uuid=2baf70d1-42bb-4437-b551-e5fed5a87abe"   # the stashed UUIDs still look up

And writes are real. Add the film the dataset is missing, get it back, keep it:

curl -X POST "$BASE/films" -H 'content-type: application/json' \
  -d '{"title":"The Boy and the Heron","director":"Hayao Miyazaki","release_date":"2023","rt_score":"96"}'
# โ†’ {"id":23,โ€ฆ}
curl "$BASE/films/23"          # โœ” it persists โ€” X-Total-Count is now 23
curl -X PATCH "$BASE/films/3" -H 'content-type: application/json' -d '{"favorite":true}'
# โ†’ your favorites button now has a backend

Pagination comes with an honest X-Total-Count header (list responses default to 20 per page โ€” use ?limit=/?page=), /m/YOUR_ID/types.ts generates a TypeScript Film interface from your records (?format=zod for Zod), and failure drills are a query param away: ?mock_delay=3000, ?mock_status=500, ?mock_ratelimit=5 โ€” the parts of a fetch exercise no polite public API will simulate for you.

4. Honest comparison

ghibliapi.herokuapp.comghibliapi.vercel.appYour copy
Alive (Sep 2026)โœ˜ 404 "No such app"โœ” ~0.5s, CORS-openโœ” yours until you delete it
Setupโ€”โœ” none at allone curl (or paste in the dashboard)
Original UUIDsโ€”โœ” preservedkept in a uuid field (ids become integers)
Exact filters / projectionโ€”โœ” ?director=, ?fields=โœ” same, plus ?select=
Substring / full-text searchโ€”โœ˜ ?title=Totoro โ†’ []โœ” ?title_like=, ?q=
Sorting / rangesโ€”โœ˜ sortBy ignoredโœ” ?sortBy=, ?rt_score_gte=
Writes persistโ€”โœ˜ 201 then GET-back 404โœ” POST/PATCH/DELETE are real
New films appear upstreamโ€”when the community updates ityou add them (see above)

The fair split: for a quick read-only viewer, the vercel.app successor is the easiest thing on this page โ€” use it and thank its maintainers. The moment your exercise needs search, sorting, a favorites button, or data that survives someone else's hosting decisions, spend the one curl and own the copy. Current status of the successor: /status/ghibli. Related: xkcd API, Rick and Morty API, GitHub Jobs (another dead tutorial API), mock any third-party API.

โšก Skip the terminal: paste your db.json in the dashboard importer (CSV, OpenAPI, Postman, and HAR work too) โ€” or create a seeded sandbox in one click. No signup.