โ† All guides

๐Ÿ“ก We check rickandmortyapi.com (and 75+ other public dev APIs) with a plain GET every 30 minutes โ€” see the live status page. As of publishing it's up, fast, and answering with 90-day immutable cache headers. This is one of the best-run free APIs there is.

Rick and Morty API alternative โ€” searches that never 404, plus writes

The Rick and Morty API is the fetch-and-render staple of modern React and GraphQL tutorials: 826 characters with hosted portrait images, episodes and locations cross-linked, REST and GraphQL, keyless, CORS open, no rate limit, aggressive caching. Community-run and genuinely excellent โ€” if you're building a read-only character grid, use it and enjoy it.

But three walls show up the moment the tutorial becomes an app (all checked live on September 18, 2026):

The fix that keeps your rendering code: copy real records into a free hosted mock API you control โ€” same field names (name, status, species, image, even the nested origin/location objects and the episode URL array, verbatim), plus a search that answers [] on a miss, the exact info/results envelope if you want it, writes that persist, and GraphQL. No signup, no key.

1. Migrate real records in two curls

# 1. pull live Ricks from the Rick and Morty API, wrap as db.json
curl "https://rickandmortyapi.com/api/character/?name=rick&status=alive" \
  | python3 -c "import sys,json; print(json.dumps({'characters': json.load(sys.stdin)['results'][:10]}))" \
  > db.json

# 2. import โ€” the response includes your project id + admin key
curl -X POST "https://mockbird.mockbird.workers.dev/api/projects/import?name=rickmorty" \
  -H 'content-type: application/json' --data-binary @db.json

That hosted 10 characters for us verbatim: numeric ids preserved, origin still the nested {"name":"Earth (C-137)","url":โ€ฆ} object, Rick's episode array all 51 URLs long, image pointing at their hosted portrait (hotlinking their avatars for a dev project is how every tutorial uses them anyway). Your card component renders it unchanged.

2. The translation table

Rick and Morty APIYour Mockbird project
/api/character/?page=2/characters?page=2&limit=20 โ€” total in the X-Total-Count header instead of info.count (or see ยง3 for the exact envelope)
?name=rick (case-insensitive substring)?name_like=rick โ€” same semantics; a miss is 200 [], never a 404
?status=alive&species=Human?status=Alive&species=Human โ€” exact match, so mind the capitalisation as stored
/api/character/1/characters/1 โ€” a bad id is a real 404 in both, but list searches never are
?page=999 past the end โ†’ 404200 [] โ€” your pagination code needs no special case
search fields limited to name/status/species/type/genderany field: ?gender=Female, ?species_ne=Human, ?q=sanchez (any-field substring), ?select=name,image
graphql โ€” { characters { results { name } } }/graphql โ€” { characters(q:"rick") { name status } charactersCount }
POST/PUT/DELETE โ†’ 404full CRUD, persists (ยง4)
curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/characters?name_like=sanchez&select=name"
# โ†’ [{"id":1,"name":"Rick Sanchez"}]

curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/characters?name_like=zzznope"
# โ†’ []   โ† 200 + empty ARRAY. The typo case renders "no results", not a crash.

3. Want their exact info/results envelope? One param

Tutorial code reads data.results and data.info.count. Reproduce that shape:

curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/characters?mock_envelope=%7B%22info%22%3A%7B%22count%22%3A%22%24total%22%7D%2C%22results%22%3A%22%24data%22%7D&name_like=sanchez&select=name"
# โ†’ {"info":{"count":1},"results":[{"id":1,"name":"Rick Sanchez"}]}

# and on a miss:
# โ†’ {"info":{"count":0},"results":[]}   โ† results is still an ARRAY. No 404, no undefined.

Set it once as the project default (PUT /api/projects/:id/settings {"envelope":โ€ฆ}) and every GET answers in their shape โ€” your fetch layer doesn't change at all. Details in docs โ†’ envelope.

4. The part their API can't do at all: writes

curl -X POST https://mockbird.mockbird.workers.dev/m/PROJECT_ID/characters \
  -H 'content-type: application/json' \
  -d '{"name":"Mockbird Rick","status":"Alive","species":"Bird-Person","gender":"unknown"}'
# โ†’ 201 {"id":โ€ฆ}   โ€” and GET /characters/:id returns it. It persists.

That upgrades the standard read-only character grid into a portfolio piece: favourites that survive refresh, an add-a-character form, an edit page, a delete button that actually deletes.

5. Rehearse the bad days they'll never show you

The Rick and Morty API is so reliable you can't practise failure against it. Yours can fail on demand:

# two 429s, then success โ€” exercise retry/backoff
curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/characters?mock_seq=429,429,200&mock_seq_key=drill1"

# 2-second response for your skeleton state
curl "https://mockbird.mockbird.workers.dev/m/PROJECT_ID/characters?mock_delay=2000"

More recipes in testing loading & error states.

Where the Rick and Morty API still wins

Credit where due โ€” a lot. The content is the product: the real show's characters, episodes, and locations, cross-linked, with hosted portrait images, served fast behind 90-day immutable caching, keyless and unlimited, maintained for years. Its GraphQL resolves relations server-side (character โ†’ episodes โ†’ characters), while our copy keeps origin/location/episode as the verbatim nested values โ€” data to render, not links to traverse. And your import is a snapshot, not a live mirror. The honest split: read-only fetch demos and GraphQL joins over the show's canon โ†’ rickandmortyapi.com, happily. Your own records with miss-proof search, writes that persist, the same envelope, and failure drills โ†’ your import.

Start now

The two-curl block in section 1, or zero setup at all:

curl https://mockbird.mockbird.workers.dev/m/demo/products?limit=3

Facts checked live on September 18, 2026: /api/character/?name=zzzznotachar, /api/episode/?name=zzzz, and /api/character/?page=999 all answer HTTP 404 {"error":"There is nothing here"}; POST /api/character, PUT /api/character/1, and DELETE /api/character/1 all answer 404 {"error":"There is nothing here."}; /api/character/99999 answers 404 {"error":"Character not found"}; /api/character/ reports info.count 826 across 42 pages; responses carry cache-control: public, max-age=7776000, immutable; ?name=RICK matched 107 characters (case-insensitive substring). Every Mockbird command on this page was run against a live project before publishing, and the scratch project was deleted after.

Full API reference in the docs. More guides: Jikan (MyAnimeList) API alternative ยท xkcd API CORS fix ยท SWAPI alternative ยท JSONPlaceholder alternative ยท Free GraphQL mock API ยท Mock API for React ยท Host a JSON file as an API. Create your API โ†’

โšก Skip the terminal: this link opens the dashboard's import panel โ€” paste the db.json from section 1 and you're done. No signup.