Skip to content
All documentation pages

Caching, limits and errors

How Block Render caches models and PNGs, which response headers to rely on, the size limits, how ETags make a repeat request free, and every error code.

Response headers

http
HTTP/2 200
content-type: image/png
cache-control: public, max-age=604800, immutable
etag: "6b6b0a0f2f0f4f2a1c7c9a1d0e2"
access-control-allow-origin: *
cross-origin-resource-policy: cross-origin
x-robots-tag: all
x-cache: MISS
x-render-ms: 3.4
x-model: block/grass_block
  • Cache-Control is immutable on renders and textures. The Minecraft version is pinned and the renderer is deterministic, so the bytes behind a URL genuinely cannot change; when the version moves, so does what the ids mean, and that is a deliberate decision rather than a background update.
  • X-Cache is HIT or MISS against the in-memory render cache.
  • X-Render-Ms is the time spent rasterising and encoding, 0 on a cache hit.
  • X-Model names the Minecraft model the render came from, which is the quickest way to see why a block looks the way it does.
  • X-Ignored-Params appears when you sent a query key that is not a parameter of this endpoint at all, which is usually a typo.
  • Access-Control-Allow-Origin: * and Cross-Origin-Resource-Policy: cross-origin, so the images work from any page and any canvas.
  • X-Robots-Tag is all on a bare render, on the five download sizes and on every raw texture, so they can appear in image search; any other combination of parameters answers noindex, because that space is unbounded and each combination is its own URL.

JSON from /api/ is public, max-age=86400. Pages carry an ETag and must-revalidate, so a revisit is a 304 rather than another 30 kB.

ETags and 304s

The ETag is a hash of everything that determines the bytes: the id, the endpoint and the resolved options. Two URLs that mean the same thing — /stone and /stone.png, size=256 and the default — get the same ETag and the same cache entry.

bash
curl -sI "https://blockrender.dev/render/block/stone.png"      # note the etag
curl -sI -H 'If-None-Match: "<that etag>"' \
     "https://blockrender.dev/render/block/stone.png"                 # 304, no body

Size limits

  • size, width and height are 8–1024 pixels.
  • The finished image may not exceed 1,048,576 pixels of area, so 1024×1024 is the largest square.
  • aa is 1–4, and is lowered automatically so that the supersampled canvas stays within 2048×2048. Ask for aa=4 at 1024 px and you get aa=2.

Speed

Measured with npm run bench on a warm process — rasterising plus PNG encoding, which is what a cache miss costs:

RequestRenderPNG
Item sprite, 256 px0.6 ms0.4 ms
Block, 128 px0.5 ms0.5 ms
Block, 256 px1.6 ms1.0 ms
Block, 512 px5.7 ms1.8 ms
Block, 1024 px23 ms5 ms
Item sprite, 1024 px7.6 ms3.2 ms

Those are medians on a developer machine. On the live server, a 512 px block forced to miss the cache reads 8–10 ms on X-Render-Ms, which covers rasterising and encoding together. The first render after a restart is several times slower — 54 ms was the very first one — while the JIT warms up, so quote a tidy single number and the next measurement contradicts it.

A repeated URL is a memory cache hit and renders nothing at all. If you want the real figure for your own request, read X-Render-Ms off the response; that beats trusting a number in prose that nobody re-measured.

Rate limits

There is no published rate limit and no key. Renders are cached in memory and answered with an ETag, so the sane way to use this is to let your own cache or CDN do its job and revalidate. Hammering the same URL in a loop is the only thing that would ever get anyone limited, and it is also the thing that costs you the most.

Errors

StatusWhen
400A parameter is out of range, malformed, or not a parameter at all in a way that cannot be ignored. The body says what was expected.
404No such id in this version, or the id exists but the game draws it with code and there is no model to rasterise. The body lists near misses.
500Something broke here. Worth reporting.

Errors are always plain text with the right status, never a PNG containing the word "error" — an image that returns 200 for a mistake is a bug that hides in a page for months.

Using the images

The textures are Mojang's. Renders made from them sit in the same place as a screenshot or a wiki image: fine for fan sites, wikis, plugin pages, Discord bots, videos and documentation; not for anything that passes itself off as an official Minecraft product, and not as a way of shipping the game's art as a texture pack. There is deliberately no whole-pack or archive download here, only individual renders and the individual textures behind them, one page at a time.

Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft. See About.