Minecraft Bedrock · read-only HTTP API · same engine as the map
20 calls.No keys.
Everything the map knows is fetchable here: the complete biome catalog of all three dimensions and the full structure list - both searchable by name - and the seed checks that run the map's own engine on the server. One call reads a seed's spawn and its surroundings, another everything about a single block column, another all 25 perlin noise channels or the extremes of one channel, and the rest answer the questions underneath: terrain height and the heightmap grid, the cave column and the whole 3D biome vertical, the desert temple's enchanted apple, the end islands, slime chunks, and the nearest-biome search. The card renderer turns any seed view into a PNG. Requests are plain GET URLs, answered with JSON, and there is no key, no account and no write operation anywhere on the surface. Every endpoint counts requests per IP in one-minute windows and reports the running quota in its headers, so a script can back off before it ever hits a wall. Each section below has a Run button that calls the live endpoint from this page and shows the real response, the timing and the quota drain.
01
The surface
How every call works
The API is one method and no state: what you send is a URL, what you get back is data. Two endpoints serve the catalogs the map is drawn from and two more search them by name, badge or id; fourteen run the seed engine itself server-side (a seed's summary and its spawn point, a point's biome column and its 3D vertical, every noise channel and a channel's extremes, a structure scan, a region grid, the terrain height and the heightmap grid, the cave column, the temple apple roll, the end islands, the slime chunks and the nearest-biome search); and one renders the share card. These conventions hold for every endpoint below.
- Base URL
- wherever this page is served from (the curl lines below each endpoint fill it in for you)
- Methods
- GET only. The API is read-only: it serves the catalogs, checks seeds and renders the cards, nothing else.
- Formats
- application/json for every endpoint except the card renderer, which answers image/png (1200 x 1400).
- Auth
- None. No keys, no tokens, no cookies. If you can open this page, you can call every endpoint.
- Coordinates
- Seeds go in exactly as the map's seed box takes them: numbers pass through, text is hashed the way Minecraft hashes text seeds. Positions are block coordinates of the dimension you ask about, bounded by the world border; the response also carries the quart and chunk coordinates the engine actually samples.
- Errors
- Every endpoint except the card renderer validates strictly and answers 400 with a JSON explanation naming the parameter and the rule it broke. The card endpoint never rejects input: it drops invalid values and falls back to its branded default card, because its job is to keep embed previews alive. A spent quota answers 429 everywhere, with a Retry-After header.
Call it from JavaScript
The whole surface fits in one small file: a call() that builds the URL, sends the fetch and hands back the parsed JSON, one helper per endpoint, and a cardUrl() for the PNG. Copy it, download it as openbase-client.js, or read it right here - the last lines ask the engine a real question and print the real answer. Rate limits apply to scripts like anyone else: honor the quota headers and back off on 429.
/* openbase-client.js - the whole OpenBase API in one small file. Plain fetch, no dependencies. Paste it into any page's console, load it with a <script type="module"> tag, or set BASE and run it from Node 18 or newer. Every helper returns the parsed JSON. */ const BASE = window.location.origin; // wherever this is served from async function call(path, params) { const url = new URL(BASE + path); if (params) for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v); const res = await fetch(url, { headers: { accept: "application/json" } }); if (!res.ok) throw new Error(path + " -> " + res.status + ": " + (await res.text())); return res.json(); } /* the catalogs */ const biomes = (dim) => call("/api/biomes", dim === undefined ? undefined : { dim }); const structures = (dim) => call("/api/structures", dim === undefined ? undefined : { dim }); /* the seed checks: the map's engine runs server-side */ const seed = (s, radius) => call("/api/seed", radius === undefined ? { seed: s } : { seed: s, radius }); const checkBiome = (s, x, z, more) => call("/api/check/biome", { seed: s, x, z, ...more }); const checkNoise = (s, x, z, more) => call("/api/check/noise", { seed: s, x, z, ...more }); const checkStructures = (s, x, z, more) => call("/api/check/structures", { seed: s, x, z, ...more }); const checkRegion = (s, x, z, more) => call("/api/check/region", { seed: s, x, z, ...more }); /* the second-wave checks: height, heightmap, spawn, caves, extremes, temple, column, end, slime and the nearest-biome search */ const checkHeight = (s, x, z, more) => call("/api/check/height", { seed: s, x, z, ...more }); const checkHeightmap = (s, x, z, more) => call("/api/check/heightmap", { seed: s, x, z, ...more }); const checkSpawn = (s) => call("/api/check/spawn", { seed: s }); const checkCaves = (s, x, z, more) => call("/api/check/caves", { seed: s, x, z, ...more }); const checkExtremes = (s, channel, x, z, more) => call("/api/check/extremes", { seed: s, channel, x, z, ...more }); const checkTemple = (s, x, z, more) => call("/api/check/temple", { seed: s, x, z, ...more }); const checkColumn = (s, x, z, more) => call("/api/check/column", { seed: s, x, z, ...more }); const checkEnd = (s, x, z, more) => call("/api/check/end", { seed: s, x, z, ...more }); const checkSlime = (s, x, z, more) => call("/api/check/slime", { seed: s, x, z, ...more }); const checkNearestBiome = (s, biome, x, z, more) => call("/api/check/nearest-biome", { seed: s, biome, x, z, ...more }); /* the catalog searches: name to id in one call */ const searchBiomes = (q, dim) => call("/api/biomes/search", dim === undefined ? { q } : { q, dim }); const searchStructures = (q, dim) => call("/api/structures/search", dim === undefined ? { q } : { q, dim }); /* the share card is a plain PNG URL - no fetch needed */ function cardUrl(s, more) { const url = new URL(BASE + "/api/og"); url.searchParams.set("seed", s); if (more) for (const [k, v] of Object.entries(more)) url.searchParams.set(k, v); return url.toString(); } /* one real question, one real answer: how high is the ground at the origin of seed 19, and how far to the nearest cherry grove? */ (async () => { const h = await checkHeight(19, 0, 0); console.log("ground at 0,0:", h.y, "in", h.biome.name); const nearest = await checkNearestBiome(19, "cherry_grove", 0, 0); console.log("nearest cherry grove:", nearest.nearest.distanceBlocks, "blocks away"); })();
02
Biomes
The biome catalog
/api/biomesJSON60 / minute / IPThe complete biome catalog, exactly as the map paints it: every biome id the engine can return in each dimension, its display name and its map color. Colors come from the cubiomes color table the map renders from, verbatim; ids follow the Java worldgen scheme the engine emits, and variant ids that can no longer generate after the 1.18 worldgen refresh are pruned at the source, so every id in the response is one a real seed can produce. Use it to translate biome ids from your own scans, build color legends, or check which ids exist in which dimension: 67 biomes across the three, 57 of them overworld.
Parameters
- dim
- default: (all three)
- Filter to one dimension: "0" overworld, "1" nether, "2" end. Anything else answers 400.
| Param | Default | Meaning |
|---|---|---|
| dim | (all three) | Filter to one dimension: "0" overworld, "1" nether, "2" end. Anything else answers 400. |
Response fields
- endpoint
- type: string
- The path, echoed back.
- count
- type: number
- Biomes across the dimensions in this response.
- dimensions
- type: array
- One entry per dimension, or just the filtered one.
- dimensions[].label
- type: string
- Overworld, Nether or End.
- dimensions[].fallbackColor
- type: string
- The neutral hex the map paints for an id it cannot classify: never a black hole.
- dimensions[].biomes[].id
- type: number
- The engine's biome id (the Java worldgen scheme).
- dimensions[].biomes[].name
- type: string
- The display name the map and popups use.
- dimensions[].biomes[].color
- type: string
- The exact hex the map paints for this biome.
| Field | Type | Meaning |
|---|---|---|
| endpoint | string | The path, echoed back. |
| count | number | Biomes across the dimensions in this response. |
| dimensions | array | One entry per dimension, or just the filtered one. |
| dimensions[].label | string | Overworld, Nether or End. |
| dimensions[].fallbackColor | string | The neutral hex the map paints for an id it cannot classify: never a black hole. |
| dimensions[].biomes[].id | number | The engine's biome id (the Java worldgen scheme). |
| dimensions[].biomes[].name | string | The display name the map and popups use. |
| dimensions[].biomes[].color | string | The exact hex the map paints for this biome. |
Response shape (truncated)
{ "endpoint": "/api/biomes", "count": 67, "dimensions": [ { "dim": 0, "label": "Overworld", "count": 57, "fallbackColor": "#8d9484", "biomes": [ { "id": 0, "name": "Ocean", "color": "#000070" }, { "id": 1, "name": "Plains", "color": "#8db360" }, { "id": 2, "name": "Desert", "color": "#fa9418" } ] }, { "dim": 1, "label": "Nether", "count": 5, "fallbackColor": "#5a5148", "biomes": [ { "id": 8, "name": "Nether Wastes", "color": "#572526" } ] } ] }
Try it live
Pick a dimension and press Run. The panel answers with the real response, the timing and the quota this call just spent.
curl "/api/biomes"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
03
Structures
The structure catalog
/api/structuresJSON60 / minute / IPThe complete structure catalog: all 32 types the map can draw, grouped by dimension (26 overworld, 4 nether, 2 end), with the badge letter, the badge color and ink, the tooltip hint, the minimum zoom where markers appear, and whether the type is on by default. engineType is the engine's internal scanner value, the number the find-structures call takes; display ids 30 (Enchanted Apple) and 31 (Zombie Village) are highlight pseudo-types computed from the desert temple and village scans, which is why their engineType reads 100 and 101. icon points at the 16 x 16 pixel-art sprite the icon marker mode stamps on the map.
Parameters
- dim
- default: (all three)
- Filter to one dimension: "0" overworld, "1" nether, "2" end. Anything else answers 400.
| Param | Default | Meaning |
|---|---|---|
| dim | (all three) | Filter to one dimension: "0" overworld, "1" nether, "2" end. Anything else answers 400. |
Response fields
- endpoint
- type: string
- The path, echoed back.
- count
- type: number
- Structure types across the dimensions in this response.
- dimensions
- type: array
- One entry per dimension, or just the filtered one.
- structures[].letter
- type: string
- The badge letter the map draws for this type (V, WM, EA...).
- structures[].color / ink
- type: string
- The badge fill hex and the letter ink (light or dark) drawn on it.
- structures[].minZoom
- type: number
- Pixels per block below which the map neither draws nor scans the type.
- structures[].defaultEnabled
- type: boolean
- Whether the map turns the type on with no stored preference.
- structures[].engineType
- type: number
- The engine's scanner enum value (100 and 101 are the apple and zombie pseudo-types).
- structures[].icon
- type: string
- Path of the 16 x 16 pixel-art sprite, servable from this origin.
| Field | Type | Meaning |
|---|---|---|
| endpoint | string | The path, echoed back. |
| count | number | Structure types across the dimensions in this response. |
| dimensions | array | One entry per dimension, or just the filtered one. |
| structures[].letter | string | The badge letter the map draws for this type (V, WM, EA...). |
| structures[].color / ink | string | The badge fill hex and the letter ink (light or dark) drawn on it. |
| structures[].minZoom | number | Pixels per block below which the map neither draws nor scans the type. |
| structures[].defaultEnabled | boolean | Whether the map turns the type on with no stored preference. |
| structures[].engineType | number | The engine's scanner enum value (100 and 101 are the apple and zombie pseudo-types). |
| structures[].icon | string | Path of the 16 x 16 pixel-art sprite, servable from this origin. |
Response shape (truncated)
{ "endpoint": "/api/structures", "count": 32, "dimensions": [ { "dim": 0, "label": "Overworld", "count": 26, "structures": [ { "id": 0, "name": "Village", "letter": "V", "color": "#F27500", "ink": "light", "hint": "Villages to loot and trade with. Desert, plains, savanna, snowy and taiga variants.", "dim": 0, "dimension": "Overworld", "minZoom": 0.5, "chunkLevel": false, "dense": false, "defaultEnabled": true, "engineType": 0, "icon": "/icons/struct-0.png" } ] } ] }
Try it live
Same playground, the structure side: the letter, the color and the zoom gate of every type, straight from the catalog the map reads.
curl "/api/structures"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
04
Seed
The seed summary
/api/seedJSON30 / minute / IPOne call reads a seed's whole opening story, server-side, from the same engine the map runs in your browser. It resolves the seed exactly like the seed box (numbers pass through, text is hashed the way Minecraft hashes it) and answers with the engine version it computed against, the overworld spawn point, the full point readout at spawn (section 05's vocabulary: biome column, terrain levels, cave biomes, climate), and every structure the engine places around spawn within your radius. The structure list is sorted nearest-first and carries the same per-type detail fields as section 07, so a script can decide whether a seed is worth opening the map for without ever loading it.
Parameters
- seed
- default: (required)
- The seed exactly as typed: numbers pass through, text is hashed the way Minecraft hashes text seeds.
- radius
- default: 8
- Chunks around spawn to scan for the nearby-structure list (0 to 64; dungeons stop at their own ceiling of 24 - the response says so when it bites). Bigger means slower, honestly so.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as typed: numbers pass through, text is hashed the way Minecraft hashes text seeds. |
| radius | 8 | Chunks around spawn to scan for the nearby-structure list (0 to 64; dungeons stop at their own ceiling of 24 - the response says so when it bites). Bigger means slower, honestly so. |
Response fields
- seed
- type: object
- The input echo: what you typed, the canonical numeric seed it resolved to, and whether it was hashed from text.
- engineVersion
- type: number
- The engine build the answer was computed against (the same constant the map reports).
- spawn
- type: object
- The overworld spawn block (x, y, z), or null when the engine cannot place one.
- spawnPoint
- type: object
- The full point readout at spawn: the section 05 body for the spawn column.
- nearbyStructures.structures
- type: array
- Hits around spawn, nearest-first, with section 07 detail fields and distances in blocks.
- nearbyStructures.truncated
- type: boolean
- Whether the response caps trimmed the list.
- nearbyStructures.dungeonRadiusChunks
- type: number
- Present only when the radius exceeded the dungeon ceiling: the radius dungeons actually scanned (same rule as section 07).
| Field | Type | Meaning |
|---|---|---|
| seed | object | The input echo: what you typed, the canonical numeric seed it resolved to, and whether it was hashed from text. |
| engineVersion | number | The engine build the answer was computed against (the same constant the map reports). |
| spawn | object | The overworld spawn block (x, y, z), or null when the engine cannot place one. |
| spawnPoint | object | The full point readout at spawn: the section 05 body for the spawn column. |
| nearbyStructures.structures | array | Hits around spawn, nearest-first, with section 07 detail fields and distances in blocks. |
| nearbyStructures.truncated | boolean | Whether the response caps trimmed the list. |
| nearbyStructures.dungeonRadiusChunks | number | Present only when the radius exceeded the dungeon ceiling: the radius dungeons actually scanned (same rule as section 07). |
Response shape (truncated)
{ "endpoint": "/api/seed", "seed": { "input": "19", "canonical": "19", "fromText": false }, "engineVersion": 265000, "spawn": { "x": 0, "y": 125, "z": 0 }, "spawnPoint": { "dimension": "Overworld", "biome": { "id": 4, "name": "Forest", "color": "#056621" }, "terrain": { "worldSurfaceY": 125, "oceanFloorY": 125, "preliminaryY": 104 }, "caveBiomes": [ { "biome": { "id": 183, "name": "Deep Dark", "color": "#031f29" }, "fromY": -13, "toY": -64 } ], "climate": [ { "key": "temperature", "label": "Temp", "value": 0.486 }, { "key": "humidity", "label": "Humid", "value": 0.031 }, { "key": "continentalness", "label": "Cont", "value": 0.271 } ] }, "nearbyStructures": { "center": { "x": 0, "z": 0 }, "radiusChunks": 8, "count": 44, "truncated": false, "structures": [ { "id": 16, "name": "Slime Chunk", "letter": "SC", "color": "#3DDC84", "blockX": -16, "blockZ": 0, "chunkX": -1, "chunkZ": 0, "y": 0, "terrainY": 126, "distanceBlocks": 16 }, "... 43 more, nearest-first" ] } }
Try it live
Type any seed, pick the scan radius, press Run: the panel shows the real summary, the timing and the quota this call spent.
curl "/api/seed?seed=19"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Text seeds hash exactly like the map's seed box (hello becomes 99162322). The first run on a fresh server warms the engine; the panel's timing shows it.
05
Point
The point readout
/api/check/biomeJSON60 / minute / IPEverything the engine knows about one block column, which is more than the map's hover can fit on screen. The surface biome arrives with its exact map color; the overworld also answers the terrain trio (world surface, ocean floor and the preliminary level), the cave-biome runs down the column as vertical intervals (deep dark, dripstone, lush), and the six climate channels that picked the biome in the first place: temperature, humidity, continentalness, erosion, weirdness and peaks-and-valleys. Ask for a y and the 3D biome at that exact height comes along, the same call the engine's column scan uses. The nether answers its cavern floor; the end answers its island ground level and height.
Parameters
- seed
- default: (required)
- Number or text, hashed like Minecraft hashes text seeds.
- x, z
- default: (required)
- Block coordinates, bounded by the world border (plus or minus 30,000,000).
- dim
- default: 0
- Dimension: "0" overworld, "1" nether, "2" end.
- y
- default: (none)
- Overworld-only: the 3D biome at this height (-64 to 320) joins the response.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | Number or text, hashed like Minecraft hashes text seeds. |
| x, z | (required) | Block coordinates, bounded by the world border (plus or minus 30,000,000). |
| dim | 0 | Dimension: "0" overworld, "1" nether, "2" end. |
| y | (none) | Overworld-only: the 3D biome at this height (-64 to 320) joins the response. |
Response fields
- position
- type: object
- The echoed block position plus the quart and chunk coordinates the engine samples on.
- biome
- type: object
- id, display name and the exact map color hex.
- terrain
- type: object
- Overworld: worldSurfaceY, oceanFloorY, preliminaryY. Nether: surfaceY. End: groundY, islandHeight. null where the engine has no surface.
- caveBiomes
- type: array
- Overworld: cave biome intervals down the column, each {biome, fromY, toY}, top first.
- climate
- type: array
- Overworld: the six climate channel values at the column's quart.
- atY
- type: object
- Present only when y was asked for: the 3D biome at that height.
| Field | Type | Meaning |
|---|---|---|
| position | object | The echoed block position plus the quart and chunk coordinates the engine samples on. |
| biome | object | id, display name and the exact map color hex. |
| terrain | object | Overworld: worldSurfaceY, oceanFloorY, preliminaryY. Nether: surfaceY. End: groundY, islandHeight. null where the engine has no surface. |
| caveBiomes | array | Overworld: cave biome intervals down the column, each {biome, fromY, toY}, top first. |
| climate | array | Overworld: the six climate channel values at the column's quart. |
| atY | object | Present only when y was asked for: the 3D biome at that height. |
Response shape
{ "endpoint": "/api/check/biome", "seed": { "input": "19", "canonical": "19", "fromText": false }, "dim": 0, "dimension": "Overworld", "position": { "x": 0, "z": 0, "quartX": 0, "quartZ": 0, "chunkX": 0, "chunkZ": 0 }, "biome": { "id": 4, "name": "Forest", "color": "#056621" }, "terrain": { "worldSurfaceY": 125, "oceanFloorY": 125, "preliminaryY": 104 }, "caveBiomes": [ { "biome": { "id": 183, "name": "Deep Dark", "color": "#031f29" }, "fromY": -13, "toY": -64 } ], "climate": [ { "key": "temperature", "label": "Temp", "value": 0.486 }, { "key": "humidity", "label": "Humid", "value": 0.031 }, { "key": "continentalness", "label": "Cont", "value": 0.271 }, { "key": "erosion", "label": "Erosion", "value": -0.471 }, { "key": "weirdness", "label": "Weird", "value": 0.436 }, { "key": "peaksAndValleys", "label": "PV", "value": -0.686 } ] }
Try it live
Point it anywhere: seed, block coordinates, dimension, and an optional y. The panel answers with the column the engine actually computes.
curl "/api/check/biome?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Negative coordinates work; y is optional and overworld-only. A junk value answers 400 with the exact rule it broke - that is the contract teaching itself.
06
Noise
The perlin readout
/api/check/noiseJSON60 / minute / IPAll 25 noise channels the engine carries, at one spot: the six climate channels, the two offset shifts plus jagged, and the sixteen cave-router noises, each with its minecraft: name in the title field. This is the data the map's Perlin Noise Map view paints from, answered per channel as the engine's own normalized byte, the channel's real range on this seed, and the reconstructed value. The reconstruction is stated, not hidden: the engine quantizes its fills to a byte grid, so value is the midpoint of that step, at most (max minus min) divided by 510 away from the exact sample. Cave-router channels sample a horizontal Y slice; ny picks it. Overworld only: the noise stack does not exist in the other dimensions.
Parameters
- seed
- default: (required)
- Number or text, hashed like Minecraft hashes text seeds.
- x, z
- default: (required)
- Block coordinates of the sample point.
- channel
- default: all
- "all", a channel key (temp, humid, cont, ero...) or its numeric id (0..24).
- ny
- default: 0
- The Y slice the cave-router channels sample at (-64 to 320); the other channels ignore it.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | Number or text, hashed like Minecraft hashes text seeds. |
| x, z | (required) | Block coordinates of the sample point. |
| channel | all | "all", a channel key (temp, humid, cont, ero...) or its numeric id (0..24). |
| ny | 0 | The Y slice the cave-router channels sample at (-64 to 320); the other channels ignore it. |
Response fields
- channels[].normalized
- type: number
- The engine's byte (0 to 255): what the noise map shades from.
- channels[].min / max
- type: number
- The channel's real range on this seed: the biome parameter table for climate, measured for the rest.
- channels[].value
- type: number
- The sample reconstructed from the byte: the midpoint of the quantization step.
- channels[].title
- type: string
- The channel's minecraft: name and one-line role.
- count
- type: number
- Channels in this response.
| Field | Type | Meaning |
|---|---|---|
| channels[].normalized | number | The engine's byte (0 to 255): what the noise map shades from. |
| channels[].min / max | number | The channel's real range on this seed: the biome parameter table for climate, measured for the rest. |
| channels[].value | number | The sample reconstructed from the byte: the midpoint of the quantization step. |
| channels[].title | string | The channel's minecraft: name and one-line role. |
| count | number | Channels in this response. |
Response shape (channel=temp)
{ "endpoint": "/api/check/noise", "seed": { "input": "19", "canonical": "19", "fromText": false }, "quantization": "value is the midpoint of the engine's byte grid: at most (max - min) / 510 off the exact sample", "position": { "x": 0, "z": 0, "quartX": 0, "quartZ": 0 }, "y": 0, "channels": [ { "id": 0, "key": "temp", "label": "Temp", "group": "climate", "title": "minecraft:temperature - the climate channel that picks hot/cold biomes", "normalized": 189, "min": -1, "max": 1, "value": 0.486 } ], "count": 1 }
Try it live
Pick a channel or take all of them. The first all-channels run on a seed measures the router ranges once; the panel's timing shows the warm-up.
curl "/api/check/noise?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
The first all-channels run on a seed measures the cave-router ranges once (the engine caches them per seed); single channels answer in milliseconds.
07
Nearby
The structure scan
/api/check/structuresJSON20 / minute / IPEvery structure the engine places near a point, with the full record: the same fields the map's popup decodes when you click a badge, plus the distance from your query center. Unlike the map's zoom gates (dense types stay hidden until you zoom in), the API scans every type of the dimension at any radius up to 64 chunks, dungeons and slime chunks included. The per-type details arrive only when they apply: village variant and zombie roll, the desert temple's enchanted-apple chest roll, igloo basements, ruin variants and clusters, fossil ores, mega and underwater ravines, ruined-portal shape and placement, dungeon spawners, bastion types, nether-fossil variants and dried ghasts, end ships. y is the engine's own placement height (0 when the finder computed none); terrainY is the terrain height under the marker in the hit's dimension, filled for every hit - over open water it is the water surface level, the same Y the map's F3 readout shows, and it is null only where the dimension has no ground at all (the End void).
Parameters
- seed
- default: (required)
- Number or text, hashed like Minecraft hashes text seeds.
- x, z
- default: (required)
- The scan center in blocks; distances are measured from here.
- dim
- default: 0
- Dimension: "0" overworld, "1" nether, "2" end.
- radius
- default: 8
- Chunks to scan around the center (0 to 64). Every non-dungeon type scans the full radius - measured, r=64 costs ~0.3s of engine work; dungeons stop at their own ceiling of 24 chunks (past it the finder's answers are layout-dependent - measured wrong on every build - so the API caps the range instead of serving wrong hits), stated as dungeonRadiusChunks when it bites. The caps below bound the answer.
- types
- default: all
- Comma list of display ids or badge letters ("V, DT, EA"), or "all" for every type of the dimension.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | Number or text, hashed like Minecraft hashes text seeds. |
| x, z | (required) | The scan center in blocks; distances are measured from here. |
| dim | 0 | Dimension: "0" overworld, "1" nether, "2" end. |
| radius | 8 | Chunks to scan around the center (0 to 64). Every non-dungeon type scans the full radius - measured, r=64 costs ~0.3s of engine work; dungeons stop at their own ceiling of 24 chunks (past it the finder's answers are layout-dependent - measured wrong on every build - so the API caps the range instead of serving wrong hits), stated as dungeonRadiusChunks when it bites. The caps below bound the answer. |
| types | all | Comma list of display ids or badge letters ("V, DT, EA"), or "all" for every type of the dimension. |
Response fields
- structures[].blockX / blockZ
- type: number
- The structure's block position (what a /tp command wants).
- structures[].chunkX / chunkZ
- type: number
- The chunk the structure generates in.
- structures[].y / terrainY
- type: number
- y is the engine's placement height (0 = the finder computed none). terrainY is the terrain height under the marker in the hit's dimension, filled for EVERY hit: over open water it is the water surface level (the map's own F3 Y), null only where the dimension has no ground (the End void).
- structures[].distanceBlocks
- type: number
- Distance from the query center, nearest-first sort.
- structures[] detail fields
- type: varies
- villageType, zombie, enchantedApple, hasBasement, oceanRuinType, isLarge, clusterSize, stairway, fossilOre, mega, underwater, portal, dungeonSpawner, bastionType, fossilVariant, driedGhast, endShip: present only for the types they belong to.
- perTypeCap / totalCap
- type: number
- The scan bounds: 256 hits per type, 512 overall; truncated flags say when they bit.
- dungeonRadiusChunks
- type: number
- Present only when the requested radius exceeded the dungeon ceiling: the radius dungeons actually scanned, while every other type scanned the full radius.
| Field | Type | Meaning |
|---|---|---|
| structures[].blockX / blockZ | number | The structure's block position (what a /tp command wants). |
| structures[].chunkX / chunkZ | number | The chunk the structure generates in. |
| structures[].y / terrainY | number | y is the engine's placement height (0 = the finder computed none). terrainY is the terrain height under the marker in the hit's dimension, filled for EVERY hit: over open water it is the water surface level (the map's own F3 Y), null only where the dimension has no ground (the End void). |
| structures[].distanceBlocks | number | Distance from the query center, nearest-first sort. |
| structures[] detail fields | varies | villageType, zombie, enchantedApple, hasBasement, oceanRuinType, isLarge, clusterSize, stairway, fossilOre, mega, underwater, portal, dungeonSpawner, bastionType, fossilVariant, driedGhast, endShip: present only for the types they belong to. |
| perTypeCap / totalCap | number | The scan bounds: 256 hits per type, 512 overall; truncated flags say when they bit. |
| dungeonRadiusChunks | number | Present only when the requested radius exceeded the dungeon ceiling: the radius dungeons actually scanned, while every other type scanned the full radius. |
Response shape (truncated)
{ "endpoint": "/api/check/structures", "seed": { "input": "19", "canonical": "19", "fromText": false }, "dim": 0, "center": { "x": 0, "z": 0, "chunkX": 0, "chunkZ": 0 }, "radiusChunks": 12, "types": "all", "perTypeCap": 256, "totalCap": 512, "count": 18, "truncated": false, "truncatedTypes": [], "structures": [ { "id": 23, "name": "Dungeon", "letter": "D", "color": "#5FA845", "blockX": 33, "blockZ": 7, "chunkX": 2, "chunkZ": 0, "y": -17, "terrainY": 128, "distanceBlocks": 33.7, "dungeonSpawner": "Zombie" }, "... 17 more, nearest-first" ] }
Try it live
Set the center, widen the radius, filter by types or take them all. The playground timing grows with the area, the same engine work the map spreads over workers.
curl "/api/check/structures?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Leave types empty for every structure of the dimension. Big radii are honest engine work: the panel's timing grows with the area you ask for.
08
Region
The region grid
/api/check/regionJSON30 / minute / IPA rectangle of the world as JSON: the map's tile fill without the canvas. One biome sample per step by step cell on the engine's own grid (quarts overworld and nether, blocks in the end), answered as rows of biome ids with the origin coordinates, a legend mapping every id present to its name and map color, and a share summary sorted largest first so coverage questions ("is this a mostly-ocean seed?") are one jq away. x and z mark the rectangle's center; w and h are its side lengths in blocks. The sampled grid is capped at 512 per side and 16,384 points, and a request over the cap answers 400 naming the numbers instead of silently clamping them.
Parameters
- seed
- default: (required)
- Number or text, hashed like Minecraft hashes text seeds.
- x, z
- default: (required)
- The CENTER of the rectangle in blocks (not its corner).
- w, h
- default: 128
- Side lengths in blocks (16 to 8192 each).
- dim
- default: 0
- Dimension: "0" overworld, "1" nether, "2" end.
- step
- default: 1
- Sampling stride in engine units (1 to 64): the same LOD ladder the map's zoomed-out tiles use.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | Number or text, hashed like Minecraft hashes text seeds. |
| x, z | (required) | The CENTER of the rectangle in blocks (not its corner). |
| w, h | 128 | Side lengths in blocks (16 to 8192 each). |
| dim | 0 | Dimension: "0" overworld, "1" nether, "2" end. |
| step | 1 | Sampling stride in engine units (1 to 64): the same LOD ladder the map's zoomed-out tiles use. |
Response fields
- grid
- type: object
- The sampled grid's width and height and the origin's native coordinates (row 0, column 0).
- rows
- type: array
- Biome id rows, north (minus z) first, matching the map's tile orientation.
- legend
- type: object
- id to {name, color} for every biome the grid contains.
- summary
- type: array
- Per-biome counts and share percentages, largest first.
- caps
- type: object
- The grid caps this endpoint enforces (512 per side, 16,384 samples).
| Field | Type | Meaning |
|---|---|---|
| grid | object | The sampled grid's width and height and the origin's native coordinates (row 0, column 0). |
| rows | array | Biome id rows, north (minus z) first, matching the map's tile orientation. |
| legend | object | id to {name, color} for every biome the grid contains. |
| summary | array | Per-biome counts and share percentages, largest first. |
| caps | object | The grid caps this endpoint enforces (512 per side, 16,384 samples). |
Response shape (truncated)
{ "endpoint": "/api/check/region", "seed": { "input": "19", "canonical": "19", "fromText": false }, "dim": 0, "dimension": "Overworld", "center": { "x": 0, "z": 0 }, "widthBlocks": 64, "heightBlocks": 64, "step": 1, "grid": { "width": 17, "height": 17, "originX": -8, "originZ": -8 }, "rows": [ [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], "... 16 more rows" ], "legend": { "4": { "id": 4, "name": "Forest", "color": "#056621" }, "182": { "id": 182, "name": "Stony Peaks", "color": "#7b8f74" } }, "summary": [ { "id": 4, "name": "Forest", "count": 276, "pct": 95.5 }, { "id": 182, "name": "Stony Peaks", "count": 13, "pct": 4.5 } ] }
Try it live
Center a window on anywhere, size it in blocks, raise step for the zoomed-out view: the panel prints the grid it filled.
curl "/api/check/region?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
x and z are the rectangle's center, not its corner. A grid over the sample caps answers 400 naming the step that fits - shrink the window or raise step.
09
Height
The height readers
How high does the ground stand - at one spot, or across a whole window? These two endpoints answer with the same calculators the map's F3 readout and the structure popups use, and the response names the one that answered, so the number's meaning is always explicit. Over open water the height is the water surface; in the End void it is honestly null, never a fake zero.
/api/check/heightJSON60 / minute / IPThe point height in any dimension: fastHeight overworld (with the full surfaceAt triple - world surface, ocean floor, preliminary height), netherSurfaceY in the nether (the cavern floor you would stand on), endGroundY in the end (the island heightmap, plus the raw island density that picks highlands against midlands). The biome under the block rides along.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- x, z
- default: (required)
- Block coordinates of the dimension, world-border bounded.
- dim
- default: 0
- 0 overworld, 1 nether, 2 end.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| x, z | (required) | Block coordinates of the dimension, world-border bounded. |
| dim | 0 | 0 overworld, 1 nether, 2 end. |
Response shape
{ "endpoint": "/api/check/height", "seed": { "input": "19", "canonical": "19", "fromText": false }, "dim": 0, "dimension": "Overworld", "position": { "x": 0, "z": 0, "quartX": 0, "quartZ": 0, "chunkX": 0, "chunkZ": 0 }, "calculator": "fastHeight", "biome": { "id": 4, "name": "Forest", "color": "#056621" }, "y": 125, "surface": { "worldSurfaceY": 125, "oceanFloorY": 125, "preliminaryY": 104 } }
Try it live
One block, one number, every dimension - the panel names the calculator that answered.
curl "/api/check/height?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
The calculator that answered rides along (fastHeight, netherSurfaceY, endGroundY) - the same number the map's F3 readout shows, over open water included.
/api/check/heightmapJSON30 / minute / IPThe heightmap grid: the terrain Y of every sample cell in a window, as a row-major grid you can render, chart or feed a plugin. The stats block carries the vertical shape (min, max, mean, median, span), and the histogram buckets the cells into 8-block Y bands - an ocean answers with one tall spike at sea level, a mountain range with a wide spread. Caps are derived from the measured per-cell cost: 256 samples a side, 16,384 cells overworld and nether, 2,048 in the End (a full-cap request stays under a second of engine time).
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- x, z
- default: (required)
- The window's CENTER in blocks.
- w, h
- default: 64 / 64
- Window extent in blocks, 4..8192 each.
- step
- default: 4
- Sampling stride in blocks, 1..512; rows and columns land on its multiples.
- dim
- default: 0
- 0 overworld (fastHeight), 1 nether (netherSurfaceY), 2 end (endGroundY, 2,048-cell cap).
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| x, z | (required) | The window's CENTER in blocks. |
| w, h | 64 / 64 | Window extent in blocks, 4..8192 each. |
| step | 4 | Sampling stride in blocks, 1..512; rows and columns land on its multiples. |
| dim | 0 | 0 overworld (fastHeight), 1 nether (netherSurfaceY), 2 end (endGroundY, 2,048-cell cap). |
Response fields
- calculator
- type: string
- Which height function answered (fastHeight, netherSurfaceY, endGroundY).
- grid
- type: object
- width x height samples, the origin block, and the block step between samples.
- rows
- type: array
- Row-major heights; rows[r][c] at (originX + c*stepBlocks, originZ + r*stepBlocks); null in the End void.
- stats
- type: object
- cells, groundCells, voidCells, min, max, mean, median, span - over the ground cells.
- histogram
- type: array
- Non-empty 8-block Y buckets, densest first: the area's vertical shape.
- center
- type: object
- The center's own height and biome.
| Field | Type | Meaning |
|---|---|---|
| calculator | string | Which height function answered (fastHeight, netherSurfaceY, endGroundY). |
| grid | object | width x height samples, the origin block, and the block step between samples. |
| rows | array | Row-major heights; rows[r][c] at (originX + c*stepBlocks, originZ + r*stepBlocks); null in the End void. |
| stats | object | cells, groundCells, voidCells, min, max, mean, median, span - over the ground cells. |
| histogram | array | Non-empty 8-block Y buckets, densest first: the area's vertical shape. |
| center | object | The center's own height and biome. |
Response shape (truncated)
{ "endpoint": "/api/check/heightmap", "seed": { "input": "19", "canonical": "19", "fromText": false }, "dim": 0, "dimension": "Overworld", "calculator": "fastHeight", "center": { "x": 0, "z": 0, "y": 125, "biome": { "id": 4, "name": "Forest", "color": "#056621" } }, "widthBlocks": 64, "heightBlocks": 64, "step": 4, "grid": { "width": 17, "height": 17, "originX": -32, "originZ": -32, "stepBlocks": 4 }, "rows": [ [126, 126, 127, 127, 128, 131, "... 11 more"], "... 16 more rows" ], "stats": { "cells": 289, "groundCells": 289, "voidCells": 0, "min": 118, "max": 139, "mean": 127.4, "median": 127, "span": 21 }, "histogram": [ { "fromY": 120, "toY": 127, "cells": 160 }, { "fromY": 128, "toY": 135, "cells": 104 }, { "fromY": 112, "toY": 119, "cells": 15 }, "... 1 more bucket" ] }
Try it live
Size the window, pick the stride, read the shape of the terrain: the panel prints the grid it filled.
curl "/api/check/heightmap?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
x and z are the window's center. Widen w/h and the caps answer 400 naming the step that fits - or raise step to cover more ground at coarser detail (the End's own, lower cap is in the message).
10
Spawn
The spawn point
/api/check/spawnJSON60 / minute / IPWhere this seed drops you, and everything about that one spot: the spawn block's coordinates, the engine version, and the full point readout at the spawn block - surface biome, the terrain triple, the cave-biome column underneath and the six climate channels. It is the cheap half of the seed summary (no structure scan), so a spawn-comparison script can walk hundreds of seeds inside the same budget a handful of full summaries would burn.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
Response shape (truncated)
{ "endpoint": "/api/check/spawn", "seed": { "input": "19", "canonical": "19", "fromText": false }, "engineVersion": 265000, "spawn": { "x": 0, "y": 125, "z": 0 }, "point": { "dim": 0, "dimension": "Overworld", "position": { "x": 0, "z": 0, "quartX": 0, "quartZ": 0, "chunkX": 0, "chunkZ": 0 }, "biome": { "id": 4, "name": "Forest", "color": "#056621" }, "terrain": { "worldSurfaceY": 125, "oceanFloorY": 125, "preliminaryY": 104 }, "caveBiomes": [ { "biome": { "id": 183, "name": "Deep Dark", "color": "#031f29" }, "fromY": -13, "toY": -64 } ], "climate": [ { "key": "temperature", "label": "Temp", "value": 0.486 }, { "key": "humidity", "label": "Humid", "value": 0.031 }, "... 4 more channels" ] } }
Try it live
One seed in, the whole opening readout out.
curl "/api/check/spawn?seed=19"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
The whole answer is one readout at the spawn block: biome, terrain triple, the cave column under it, the six climate channels. The first run on a fresh server also warms the engine.
11
Underground
The underground readers
Two questions every digger asks: which cave biomes sit under this spot, and what biome surrounds me at THIS height? The cave scan reads the column's cave-biome runs; the 3D column reads the engine's biome grid down the whole vertical, surface to bedrock. Overworld only - the cave noise stack and the 3D climate grid do not exist in the other dimensions.
/api/check/cavesJSON60 / minute / IPThe cave column with a start depth you pick: every run of cave biome the column passes through - lush caves, dripstone caves, the deep dark - as Y bands with the block count each, plus the totals (coverage, deepest Y, largest run) and the surface context. Lower topY to ask only about a mine level; the deep dark's band is the ancient-city hunting ground.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- x, z
- default: (required)
- Block coordinates, overworld.
- topY
- default: 320
- The Y the scan starts down from, -64..320.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| x, z | (required) | Block coordinates, overworld. |
| topY | 320 | The Y the scan starts down from, -64..320. |
Response shape
{ "endpoint": "/api/check/caves", "seed": { "input": "19", "canonical": "19", "fromText": false }, "position": { "x": 0, "z": 0, "quartX": 0, "quartZ": 0, "chunkX": 0, "chunkZ": 0 }, "topY": 320, "surface": { "biome": { "id": 4, "name": "Forest", "color": "#056621" }, "worldSurfaceY": 125 }, "runs": [ { "biome": { "id": 183, "name": "Deep Dark", "color": "#031f29" }, "fromY": -13, "toY": -64, "blocks": 52 } ], "truncated": false, "stats": { "runs": 1, "totalBlocks": 52, "deepestY": -64, "largest": { "biome": "Deep Dark", "blocks": 52 } } }
Try it live
One column, every cave biome band under it.
curl "/api/check/caves?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Deep dark under a forest here - lower topY to ask about a mine level only, or move x/z to hunt ancient city ground (the deep dark band shows as its own run).
/api/check/columnJSON60 / minute / IPThe 3D biome column: the engine's biome grid sampled at every step blocks from -64 to 320 and compressed into runs, top-down the way a player descends. It answers what the surface reader cannot - where the deep dark band ends, what the deepslate layer reads as, whether lush caves can generate at your mine's height. Step 4 is the grid's own vertical cell size; step 1 reads every block.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- x, z
- default: (required)
- Block coordinates, overworld.
- step
- default: 4
- Sampling stride in blocks, 1..64; run edges land on its multiples.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| x, z | (required) | Block coordinates, overworld. |
| step | 4 | Sampling stride in blocks, 1..64; run edges land on its multiples. |
Response shape
{ "endpoint": "/api/check/column", "seed": { "input": "19", "canonical": "19", "fromText": false }, "position": { "x": 0, "z": 0, "quartX": 0, "quartZ": 0, "chunkX": 0, "chunkZ": 0 }, "step": 4, "yRange": { "min": -64, "max": 320, "samples": 97 }, "surface": { "biome": { "id": 4, "name": "Forest", "color": "#056621" }, "y": 125 }, "runs": [ { "biome": { "id": 4, "name": "Forest", "color": "#056621" }, "fromY": -12, "toY": 320, "samples": 84 }, { "biome": { "id": 183, "name": "Deep Dark", "color": "#031f29" }, "fromY": -64, "toY": -16, "samples": 13 } ] }
Try it live
The whole vertical in one readout: surface to bedrock, as biome runs.
curl "/api/check/column?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Top-down biome runs for the whole vertical: the deep dark band sits at the bottom here. Step 4 is the 3D grid's own cell size; step 1 reads every block of the -64..320 range.
12
Extremes
The noise extremes
/api/check/extremesJSON30 / minute / IPWhere does a channel bottom out and peak around you? The engine fills one noise channel over a square window and the response names the lowest and highest cells it found - block position, the reconstructed value (the byte-grid midpoint, the quantization the noise reader states), the engine's own byte, and the distance from your center. Climate channels answer where the coldest or driest ground sits; cave-router channels take ny because they are 3D. Ties keep the first cell in scan order, so the same query always names the same spot.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- x, z
- default: (required)
- The window's center in blocks, overworld.
- channel
- default: (required)
- ONE channel key (temp, cont, cavecheese...) or its numeric id - not all.
- radius
- default: 1024
- Window radius in blocks, 16..8192; the square window spans this each way.
- ny
- default: 0
- The Y slice for cave-router channels, -64..320.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| x, z | (required) | The window's center in blocks, overworld. |
| channel | (required) | ONE channel key (temp, cont, cavecheese...) or its numeric id - not all. |
| radius | 1024 | Window radius in blocks, 16..8192; the square window spans this each way. |
| ny | 0 | The Y slice for cave-router channels, -64..320. |
Response shape
{ "endpoint": "/api/check/extremes", "seed": { "input": "19", "canonical": "19", "fromText": false }, "dim": 0, "dimension": "Overworld", "channel": { "id": 0, "key": "temp", "label": "Temp", "group": "climate", "title": "minecraft:temperature - the climate channel that picks hot/cold biomes", "min": -1, "max": 1 }, "center": { "x": 0, "z": 0 }, "radiusBlocks": 1024, "ny": 0, "scan": { "stepBlocks": 8, "samples": 66049, "gridWidth": 257, "gridHeight": 257, "originQuartX": -256, "originQuartZ": -256 }, "lowest": { "x": 1024, "z": 1016, "value": 0.11, "normalized": 141, "distanceBlocks": 1442.5 }, "highest": { "x": -1024, "z": 1016, "value": 0.58, "normalized": 201, "distanceBlocks": 1442.5 } }
Try it live
Pick a channel, widen the window, and the panel names the two cells the scan crowned.
curl "/api/check/extremes?seed=19&x=0&z=0&channel=temp"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Channel picks the question (temp: coldest and hottest spot; cont: where the ocean floor starts). Ties keep the first cell in scan order, so the same query always names the same spot.
13
Temple
The temple apple check
/api/check/templeJSON30 / minute / IPThe classic question, one call: does THIS chunk's desert temple hide the enchanted golden apple? Radius 0 (the default) answers the chunk covering your x and z - whether a temple generates there at all, and whether its chest roll yields the apple. A radius widens the answer into an apple hunt: every desert temple in the chunk window, apple carriers first, each with its chunk and block position, the terrain Y under the marker and the distance from the query point. The example below is a real apple chunk of seed 19.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- x, z
- default: (required)
- Block coordinates, overworld; the covering chunk is derived from them.
- radius
- default: 0
- 0: the covering chunk alone; 1..64: every desert temple in the chunk window.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| x, z | (required) | Block coordinates, overworld; the covering chunk is derived from them. |
| radius | 0 | 0: the covering chunk alone; 1..64: every desert temple in the chunk window. |
Response shape
{ "endpoint": "/api/check/temple", "seed": { "input": "19", "canonical": "19", "fromText": false }, "position": { "x": -98184, "z": 97880, "chunkX": -6137, "chunkZ": 6117 }, "temple": true, "enchantedApple": true }
Try it live
The default coordinates ARE seed 19's apple temple - press Run and watch the booleans flip true.
curl "/api/check/temple?seed=19&x=-98184&z=97880"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
The default x/z is seed 19's own apple temple chunk (temple true, enchantedApple true). Radius 0 asks the covering chunk alone; raise it to hunt every temple in the window, apple carriers first.
14
The End
The end islands
/api/check/endJSON30 / minute / IPThe End's own two numbers at one spot: groundY - the island heightmap the End City ground rule itself uses, honestly null in the void - and islandHeight, the raw island density that separates highlands from midlands from small islands. The biome and the distance from the origin ride along. A radius turns the point into a census: island against void cells, the highest ground with its coordinates, and the biome mix of the window - the where-do-I-build question, answered with counts.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- x, z
- default: (required)
- Block coordinates of the end.
- radius
- default: 0
- 0: the point alone; 1..1024 blocks: the island census window.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| x, z | (required) | Block coordinates of the end. |
| radius | 0 | 0: the point alone; 1..1024 blocks: the island census window. |
Response shape (radius 512)
{ "endpoint": "/api/check/end", "seed": { "input": "19", "canonical": "19", "fromText": false }, "position": { "x": 0, "z": 0, "chunkX": 0, "chunkZ": 0 }, "distanceFromOrigin": 0, "biome": { "id": 9, "name": "The End", "color": "#8080ff" }, "groundY": 59, "islandHeight": 80, "scan": { "radiusBlocks": 512, "stepBlocks": 26, "samples": 1600, "islandCells": 41, "voidCells": 1559, "highest": { "x": -18, "z": 8, "groundY": 62, "islandHeight": 74.7 }, "biomes": [ { "biome": { "id": 9, "name": "The End", "color": "#8080ff" }, "cells": 1600, "pct": 100 } ] } }
Try it live
The main island at the origin, or fly out - (10000, 10000) is small-islands country with 650 island cells in a 256-block window.
curl "/api/check/end?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Radius 0 reads one spot; a radius turns the point into the island census (island against void cells, the highest ground, the biome mix). The void answers groundY null - honestly, never 0.
15
Slime
The slime chunk check
/api/check/slimeJSON60 / minute / IPIs THIS chunk a slime chunk? Radius 0 answers the chunk covering your x and z with one boolean - the same rule the map's SC layer draws, the first question of every slime farm. A radius lists every slime chunk in the window instead, nearest first, with chunk and block coordinates and distances, under the same 512-hit ceiling the structure scan carries. Slime chunks are a chunk-level rule, so positions are chunk centers - the example's 27 chunks are the seed-19 origin neighborhood at radius 8.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- x, z
- default: (required)
- Block coordinates, overworld; the covering chunk is derived from them.
- radius
- default: 0
- 0: the covering chunk alone; 1..64: every slime chunk in the chunk window.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| x, z | (required) | Block coordinates, overworld; the covering chunk is derived from them. |
| radius | 0 | 0: the covering chunk alone; 1..64: every slime chunk in the chunk window. |
Response shape (radius 8, truncated)
{ "endpoint": "/api/check/slime", "seed": { "input": "19", "canonical": "19", "fromText": false }, "position": { "x": 0, "z": 0, "chunkX": 0, "chunkZ": 0 }, "slimeChunk": false, "chunk": { "x": 0, "z": 0, "blockX": 8, "blockZ": 8 }, "scan": { "radiusChunks": 8, "count": 27, "truncated": false, "chunks": [ { "chunkX": -1, "chunkZ": 0, "blockX": -16, "blockZ": 0, "distanceBlocks": 16 }, { "chunkX": 0, "chunkZ": -2, "blockX": 0, "blockZ": -32, "distanceBlocks": 32 }, { "chunkX": 1, "chunkZ": -2, "blockX": 16, "blockZ": -32, "distanceBlocks": 35.8 }, "... 24 more, nearest-first" ] } }
Try it live
One boolean at radius 0; raise it and the neighborhood's slime map arrives.
curl "/api/check/slime?seed=19&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Radius 0 answers the chunk covering x/z with one boolean; a radius lists every slime chunk in the window, nearest first - the seed-19 origin neighborhood carries 27 of them at radius 8.
16
Nearest
The nearest-biome search
/api/check/nearest-biomeJSON20 / minute / IPHow far is the nearest cherry grove, warped forest, deep dark - and in which direction? The map's own LOD ladder as a search: expanding square passes around your start, each one the same 513 x 513 fill class the OG card renders from. The first pass that finds the biome answers with the nearest cell, the first 64 matches, and - stated, not hidden - the pass's own resolution in blocks, because at coarser passes the true edge may sit between samples. A biome that never appears reports found false with the widest window searched. Works in all three dimensions.
Parameters
- seed
- default: (required)
- The seed exactly as the map's seed box takes it.
- biome
- default: (required)
- The dimension's biome id or name (exact, or a fragment matching exactly one; ambiguous fragments answer 400 with the candidates).
- x, z
- default: (required)
- The search start in blocks of the dimension.
- dim
- default: 0
- 0 overworld, 1 nether, 2 end.
| Param | Default | Meaning |
|---|---|---|
| seed | (required) | The seed exactly as the map's seed box takes it. |
| biome | (required) | The dimension's biome id or name (exact, or a fragment matching exactly one; ambiguous fragments answer 400 with the candidates). |
| x, z | (required) | The search start in blocks of the dimension. |
| dim | 0 | 0 overworld, 1 nether, 2 end. |
Response shape (truncated)
{ "endpoint": "/api/check/nearest-biome", "seed": { "input": "19", "canonical": "19", "fromText": false }, "target": { "id": 185, "name": "Cherry Grove", "color": "#ff91c8" }, "start": { "x": 0, "z": 0 }, "found": true, "nearest": { "x": 1200, "z": -416, "distanceBlocks": 1270.1 }, "matches": [ { "x": 1200, "z": -416, "distanceBlocks": 1270.1 }, { "x": 1200, "z": -432, "distanceBlocks": 1275.4 }, { "x": 1184, "z": -480, "distanceBlocks": 1277.6 }, "... 61 more, nearest-first" ], "scan": { "passes": [ { "radiusBlocks": 1024, "stepBlocks": 4, "samples": 263169 }, { "radiusBlocks": 4096, "stepBlocks": 16, "samples": 263169 } ], "resolutionBlocks": 16, "searchedBlocks": 4096 } }
Try it live
Name a biome, drop a pin, press Run - the search walks outward until the biome answers.
curl "/api/check/nearest-biome?seed=19&biome=cherry_grove&x=0&z=0"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
The search states its own resolution: 4 blocks inside the first kilometer, then 16, 64, 256 as it widens. An ambiguous fragment (deep) answers 400 listing every candidate - pass the exact name or the id.
17
Search
The catalog searches
Name to id, in one call: the two searches walk the same tables the catalogs serve, matching names case-insensitively, badge letters and numeric ids, exact hits first. They answer the questions scripts actually hit - what's the id of the pale garden, what was SC again - without paging through the whole catalog. Pure table work: no engine run, generous budgets.
/api/biomes/searchJSON60 / minute / IPBiome names and ids across all three dimensions at once (or one, with dim): every match carries its dimension, display name and map color, exact matches ranked first.
Parameters
- q
- default: (required)
- A name fragment or an id, 2+ characters (pale, deep, 186...).
- dim
- default: (all three)
- Narrow to one dimension: 0, 1 or 2.
| Param | Default | Meaning |
|---|---|---|
| q | (required) | A name fragment or an id, 2+ characters (pale, deep, 186...). |
| dim | (all three) | Narrow to one dimension: 0, 1 or 2. |
Response shape
{ "endpoint": "/api/biomes/search", "query": "pale", "count": 1, "truncated": false, "matches": [ { "dim": 0, "dimension": "Overworld", "id": 186, "name": "Pale Garden", "color": "#696d95" } ] }
Try it live
Type a fragment, get the ids - try deep for the six-biome deep family.
curl "/api/biomes/search?q=pale"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Exact matches rank first, then prefixes, then substrings, across all three dimensions at once. Try deep for the six-biome deep family, or an id for its one row.
/api/structures/searchJSON60 / minute / IPStructure names, badge letters (the map's one-letter badges, case-insensitive) and ids, across dimensions or narrowed by dim; every hit carries the hint line, the dimension and the chunk-level flag.
Parameters
- q
- default: (required)
- A name fragment, badge letter or id, 2+ characters (slime, SC, city, 16...).
- dim
- default: (all three)
- Narrow to one dimension: 0, 1 or 2.
| Param | Default | Meaning |
|---|---|---|
| q | (required) | A name fragment, badge letter or id, 2+ characters (slime, SC, city, 16...). |
| dim | (all three) | Narrow to one dimension: 0, 1 or 2. |
Response shape
{ "endpoint": "/api/structures/search", "query": "slime", "count": 1, "truncated": false, "matches": [ { "id": 16, "name": "Slime Chunk", "letter": "SC", "color": "#3DDC84", "hint": "Slime chunks. Slimes spawn here at night below y40.", "dim": 0, "dimension": "Overworld", "chunkLevel": true } ] }
Try it live
SC is the slime chunk's badge - try city, ruin, or your own fragment.
curl "/api/structures/search?q=slime"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
Names, badge letters (the map's one-letter badges) and ids all match - SC is the slime chunk's badge. Every hit carries the dimension and the chunk-level flag.
18
Cards
The card renderer
/api/ogPNG 1200 x 140030 / minute / IPThe renderer behind the Discord embed: a 1200 x 1400 PNG of any seed view, computed server-side by the same WASM engine the map runs in your browser. Every parameter of a share link works here, so you can point it at a seed, a center, a zoom, a dimension, a noise layer or a structure marker set and get exactly that view as an image. Without a seed it answers with the branded default card, and invalid values are dropped rather than rejected: the route's contract is that an embed preview never breaks.
Parameters
- seed
- default: (default card)
- The seed exactly as typed: numbers pass through, text is hashed the way Minecraft hashes text seeds.
- x, z
- default: spawn / 0,0
- View center in blocks of the dimension (the overworld default is the seed's spawn point).
- zoom
- default: 2 (0.5 end)
- Canvas scale; the map's own bounds are 0.25 to 20.
- dim
- default: 0
- 0 overworld, 1 nether, 2 end.
- layer
- default: (biome colors)
- A noise view id (temp, humid, cavecheese...): overworld only, swaps the biome colors for that perlin channel.
- ny
- default: 0
- The Y slice for cave channels, -64 to 320.
- st
- default: (site defaults)
- Enabled structures as a base36 bitmask, one bit per display id 0 to 31.
- structures
- default: (site defaults)
- true or false: the whole structure layer gate. st wins when both are present.
- structure_icon
- default: letter
- letter badges or the pixel-art icon sprites.
- spawn
- default: true
- The gold spawn marker and SPAWN microlabel on the card.
- compass
- default: true
- The pixel compass rose.
- scalebar
- default: true
- The real scale bar.
- grid
- default: false
- The 16-block chunk grid overlay.
| Param | Default | Meaning |
|---|---|---|
| seed | (default card) | The seed exactly as typed: numbers pass through, text is hashed the way Minecraft hashes text seeds. |
| x, z | spawn / 0,0 | View center in blocks of the dimension (the overworld default is the seed's spawn point). |
| zoom | 2 (0.5 end) | Canvas scale; the map's own bounds are 0.25 to 20. |
| dim | 0 | 0 overworld, 1 nether, 2 end. |
| layer | (biome colors) | A noise view id (temp, humid, cavecheese...): overworld only, swaps the biome colors for that perlin channel. |
| ny | 0 | The Y slice for cave channels, -64 to 320. |
| st | (site defaults) | Enabled structures as a base36 bitmask, one bit per display id 0 to 31. |
| structures | (site defaults) | true or false: the whole structure layer gate. st wins when both are present. |
| structure_icon | letter | letter badges or the pixel-art icon sprites. |
| spawn | true | The gold spawn marker and SPAWN microlabel on the card. |
| compass | true | The pixel compass rose. |
| scalebar | true | The real scale bar. |
| grid | false | The 16-block chunk grid overlay. |
Response
An image/png body, 1200 x 1400, cacheable for a day in the client and a week on shared proxies. Every response also carries the quota headers, and a spent budget answers 429 JSON (section 05). There is no 500 case: on any internal failure the route still answers with the default card.
Try it live
Type a seed, pick a dimension, press Run: the panel renders the actual card this endpoint would hand to Discord for that link. First run pays a one-time engine warm-up; later runs reuse the loaded module.
curl "/api/og?seed=19"Not run yet. Press Run to call this endpoint live from this page and see the real response, timing and quota.
An empty seed field calls the endpoint bare, which answers with the branded default card. Text seeds are hashed the way Minecraft hashes them, exactly like the map's seed box.
19
Limits
Rate limits
Every endpoint counts requests per client IP in fixed 60-second windows, and the budget follows the real cost of the call. The catalogs and their searches serialize plain tables (the generous class). The point reads run the engine but finish in milliseconds once warm. The seed summary, the region grid, the heightmap grid and the card renderer run the engine for real work; the structure scan and the nearest-biome search are the heaviest, so they carry the tightest budgets. The quota rides along on every response in three headers, and a request over the limit receives 429 with a Retry-After header instead of data. The counters live in the server process's memory: a restart resets them, and that is the whole persistence story.
The budgets
- /api/biomes
- limit: 60 / 60s / IP
- Serializes the biome tables: cheap, generous.
- /api/structures
- limit: 60 / 60s / IP
- Serializes the structure catalog: same class as biomes.
- /api/seed
- limit: 30 / 60s / IP
- Engine init plus the spawn readout and a structure scan around it.
- /api/check/biome
- limit: 60 / 60s / IP
- One engine column: milliseconds once the engine is warm.
- /api/check/noise
- limit: 60 / 60s / IP
- Point noise samples; the first all-channels run per seed also measures the router ranges.
- /api/check/structures
- limit: 20 / 60s / IP
- The heavy scan: every type over the radius you pick (dungeons stop at their own measured ceiling), tightest budget on the surface.
- /api/check/region
- limit: 30 / 60s / IP
- A tile-class biome fill, bounded by the grid caps.
- /api/og
- limit: 30 / 60s / IP
- Runs the engine, scans markers and encodes a PNG.
- /api/check/height
- limit: 60 / 60s / IP
- One height call plus the surface triple: point-read class.
- /api/check/heightmap
- limit: 30 / 60s / IP
- A grid of height calls, capped by the measured per-cell cost (the End's cap is its own, lower one).
- /api/check/spawn
- limit: 60 / 60s / IP
- The spawn search plus one point readout at the spawn block.
- /api/check/caves
- limit: 60 / 60s / IP
- One cave-biome column scan: point-read class.
- /api/check/extremes
- limit: 30 / 60s / IP
- One channel's noise fill over the window: a tile-class fill plus the range measurement.
- /api/check/temple
- limit: 30 / 60s / IP
- The apple roll at one chunk, or a desert-temple scan when radius > 0.
- /api/check/column
- limit: 60 / 60s / IP
- The 3D biome ladder (up to 385 point reads at step 1).
- /api/check/end
- limit: 30 / 60s / IP
- End lookups are ~310us a cell: the point is cheap, the optional census is the budget.
- /api/check/slime
- limit: 60 / 60s / IP
- The chunk rule at one chunk, or a slime scan when radius > 0.
- /api/check/nearest-biome
- limit: 20 / 60s / IP
- Expanding LOD passes, each a 513 x 513 fill (~100ms a pass): the tightest engine budget with the structure scan.
- /api/biomes/search
- limit: 60 / 60s / IP
- Pure table search over the biome catalog: cheap, generous.
- /api/structures/search
- limit: 60 / 60s / IP
- Pure table search over the structure catalog: same class as biomes.
| Endpoint | Limit | Meaning |
|---|---|---|
| /api/biomes | 60 / 60s / IP | Serializes the biome tables: cheap, generous. |
| /api/structures | 60 / 60s / IP | Serializes the structure catalog: same class as biomes. |
| /api/seed | 30 / 60s / IP | Engine init plus the spawn readout and a structure scan around it. |
| /api/check/biome | 60 / 60s / IP | One engine column: milliseconds once the engine is warm. |
| /api/check/noise | 60 / 60s / IP | Point noise samples; the first all-channels run per seed also measures the router ranges. |
| /api/check/structures | 20 / 60s / IP | The heavy scan: every type over the radius you pick (dungeons stop at their own measured ceiling), tightest budget on the surface. |
| /api/check/region | 30 / 60s / IP | A tile-class biome fill, bounded by the grid caps. |
| /api/og | 30 / 60s / IP | Runs the engine, scans markers and encodes a PNG. |
| /api/check/height | 60 / 60s / IP | One height call plus the surface triple: point-read class. |
| /api/check/heightmap | 30 / 60s / IP | A grid of height calls, capped by the measured per-cell cost (the End's cap is its own, lower one). |
| /api/check/spawn | 60 / 60s / IP | The spawn search plus one point readout at the spawn block. |
| /api/check/caves | 60 / 60s / IP | One cave-biome column scan: point-read class. |
| /api/check/extremes | 30 / 60s / IP | One channel's noise fill over the window: a tile-class fill plus the range measurement. |
| /api/check/temple | 30 / 60s / IP | The apple roll at one chunk, or a desert-temple scan when radius > 0. |
| /api/check/column | 60 / 60s / IP | The 3D biome ladder (up to 385 point reads at step 1). |
| /api/check/end | 30 / 60s / IP | End lookups are ~310us a cell: the point is cheap, the optional census is the budget. |
| /api/check/slime | 60 / 60s / IP | The chunk rule at one chunk, or a slime scan when radius > 0. |
| /api/check/nearest-biome | 20 / 60s / IP | Expanding LOD passes, each a 513 x 513 fill (~100ms a pass): the tightest engine budget with the structure scan. |
| /api/biomes/search | 60 / 60s / IP | Pure table search over the biome catalog: cheap, generous. |
| /api/structures/search | 60 / 60s / IP | Pure table search over the structure catalog: same class as biomes. |
The quota headers
- X-RateLimit-Limit
- on: every response
- The budget for this endpoint (per IP, per window).
- X-RateLimit-Remaining
- on: every response
- Requests left in the current window, draining as you call.
- X-RateLimit-Reset
- on: every response
- Epoch seconds when the current window reopens.
- Retry-After
- on: on 429 only
- Seconds until the window resets; wait, then call again.
| Header | On | Meaning |
|---|---|---|
| X-RateLimit-Limit | every response | The budget for this endpoint (per IP, per window). |
| X-RateLimit-Remaining | every response | Requests left in the current window, draining as you call. |
| X-RateLimit-Reset | every response | Epoch seconds when the current window reopens. |
| Retry-After | on 429 only | Seconds until the window resets; wait, then call again. |
The 429 body (example)
{ "error": "rate_limited", "endpoint": "/api/og", "limit": 30, "retryAfterSeconds": 27, "resetAt": 1760226800 }
The client IP is read from the proxy's X-Forwarded-For header, so every visitor behind the proxy counts separately; direct access without a proxy simply shares one bucket. And you can watch a 429 happen with your own eyes: run the card endpoint 31 times inside a minute, and the last response will tell you, down to the second, when the window reopens.