rcemaps.com← Back to the map generator

rcemaps API

Map images for any Rust Console Edition seed, over plain HTTP. No signup, no OAuth — point an <img> or a Discord embed at a URL and you get a PNG.

Quick start

https://rcemaps.com/api/v1/map.png?seed=1234567&size=4500&clean=1

That is the entire integration for most bots. In discord.js:

const seed = 1234567, size = 4500;
const url = `https://rcemaps.com/api/v1/map.png?seed=${seed}&size=${size}&clean=1`;

await interaction.reply({ embeds: [{
  title: `Rust Console — seed ${seed}`,
  url:   `https://rcemaps.com/?seed=${seed}&size=${size}`,
  image: { url },
}] });

Discord fetches the image itself and caches it, so a popular map costs you one request no matter how many people see the message.

Authentication

Optional. Without a key you are metered by IP at the anonymous rate, which is enough for a small bot. If you need more, ask for a free key and send it as an X-API-Key header. A ?key= query parameter also works where headers are awkward, but prefer the header — query strings end up in server logs and browser history.

curl -H "X-API-Key: rce_…" \
     "https://rcemaps.com/api/v1/limits"

Rate limits

Two separate budgets, because the two kinds of request cost very different things. Asking for a map that has been rendered before is nearly free; asking for one that has not means generating it. Only the second draws from the “new maps” budget — re-posting maps you have already requested is effectively unmetered.

TierRequestsNew maps
anon60/min (burst 30)5/min (burst 3)
key600/min (burst 120)60/min (burst 20)

Every response carries X-RateLimit-Limit and X-RateLimit-Remaining; a 429 also carries Retry-After. Check X-Cache on an image response to see whether you paid for a generation: HIT means you did not.

If you are backfilling a lot of seeds, request them slowly rather than in a burst, and cache the PNGs at your end. Ask for a key and say what you are building — that is easier for both of us than being rate-limited.

Endpoints

GET /api/v1/map.png

The map image, 512×512 PNG. Takes the parameters below.

GET /api/v1/map.json

Metadata for the same map: the image URL, a link to the interactive version, land_pct when known, whether it is already rendered, and a projection block giving the world→pixel transform for overlays. Validates your parameters without generating anything.

GET /api/v1/servers

Which seeds the official Console servers are currently running, and how many servers are on each. Use it to show “your server’s map” without asking anyone to type a seed.

GET /api/v1/discover

A rolling feed of freshly generated maps — the same one the site’s Discover tab shows. Every entry carries a ready-to-embed image URL, so a bot can post a new map on a timer without generating anything itself. Newest first. Filter with size, page with limit, and poll cheaply with after (pass the newest value from your last reply and you get only what has appeared since).

GET /api/v1/ground

The ground height (world Y) at any point of a map, with a safe spawn height above it — for spawn commands, route planners, anything that needs to know where the ground is. One point with x and z, or up to 50 on one map with points=x,z;x,z. See Ground height below.

GET /api/v1/limits

Your tier and how much of each budget is left.

Parameters

NameDefaultAcceptsNotes
seedrequired0 – 2147483647The world seed.
size45001000, 1500, 2000, 2500, 3000, 3500, 4000, 4500World size in metres.
styleingameingame, height, biome, topoMap view: the in-game look, a heightmap, biome colours, or topography.
qualityfastfast, qualityquality resolves finer terrain detail and is slower to produce.
clean00 or 11 drops the grid and the info bar, leaving just the map — best for a Discord embed.

The Discover feed

Poll it for something new to post. The reply gives you maps (newest first), count, total matching your filter, and newest — feed that back as after next time so you only ever fetch what you have not seen. Each map’s img is the full 512 px picture; thumb is a small copy (384 px, about a tenth of the size) for a grid or a list.

https://rcemaps.com/api/v1/discover?size=4500&limit=5
{
  "maps": [
    { "seed": 1288469066, "size": 4500,
      "land": 42.7,
      "img": "https://rcemaps.com/discover/img/4ac944e5.png",
      "thumb": "https://rcemaps.com/discover/thumb/1/4ac944e5.webp",
      "url": "https://rcemaps.com/?seed=1288469066&size=4500",
      "ts": 1788072848 }
  ],
  "count": 5, "total": 118, "newest": 1788072848
}

Drawing on top of the map

If you are plotting anything — player positions, monuments, a heatmap, your own markers — you need to know where a world coordinate lands in the image. map.json tells you, in a projection block, so you never have to measure it yourself or re-check it when something changes.

Two things catch people out, so they are stated outright in the reply: the map fills the whole image (there is no border to subtract), and the z axis is inverted — north is +z in the world but the top of the image, where y is 0.

{
  "projection": {
    "image": { "width": 512, "height": 512 },
    "world": { "size": 4500, "min_x": -2250, "max_x": 2250, "min_z": -2250, "max_z": 2250 },
    "metres_per_pixel": 8.7890625,
    "origin_px": { "x": 256, "y": 256 }
  }
}

Which is two lines in any language:

px = (x + size / 2) / size * width
py = height - (z + size / 2) / size * height

and back the other way, for a click on the image:

x = px / width * size - size / 2
z = size / 2 - py / height * size

These are the same numbers this site uses to draw its own monument markers, so anything you place with them lines up with anything we draw.

Ground height

/api/v1/ground gives the ground’s world Y at a point, so you can build a spawn or teleport command without going in-game to find it. Pass the map exactly as you would to map.png — seed, size and any terrain commands — plus x and z, or points=x,z;x,z for up to 50 at once.

https://rcemaps.com/api/v1/ground?seed=11239&size=4500&points=1125,1125;0,0

Each point comes back with ground_y, a spawn_y a safe margin above it (5 m unless you pass margin=2|5|10|20), underwater and water_depth, and its grid square. In the sea, spawn_y is measured up from the water surface.

How close is it? On unmodified 4500 maps the typical error is about half a metre. The margin is there because monuments, roads, rivers and canyons reshape the ground after the map is made, and this can’t see them. Each reply lists, per margin, how much of the map that margin still isn’t enough for (margins) — they are measured, not guessed. Reading high is harmless, the thing just drops; reading low would bury it, so the margin is one-sided on purpose.

Lookups read the map’s height data, which the server keeps in memory only for maps generated recently. When it is there the answer is instant and costs nothing extra. When it isn’t, the map is generated first, which costs one new-map token — the same as an uncached map.png. Fetching map.png first doesn’t avoid it: a cached picture keeps no heights. So ask for all your points on a map in one call — up to 50 cost at most one token. Out of tokens, you get a 429 with Retry-After: wait that long and try again.

Terrain commands

Every terrain.* and env.oceanlevel command the game takes works here too, so you can render the map a server is actually running rather than the stock one for that seed. Drop the terrain. prefix and pass the command as a query parameter — terrain.elevation_hill 0.8 becomes elevation_hill=0.8, and env.oceanlevel 5 becomes oceanlevel=5.

So a server booted with:

server.seed 1234567
server.worldsize 4500
--terrain.elevation_hill 0.8
--terrain.center_falloff 1200
env.oceanlevel 5

is this request:

https://rcemaps.com/api/v1/map.png?seed=1234567&size=4500&clean=1
  &elevation_hill=0.8&center_falloff=1200&oceanlevel=5

The ten noise_* commands take Rust's own syntax, url-encoded because of the = and ,:

&noise_base_land=oct%3D6%2Cfreq%3D1%2Camp%3D4%2Coffset%3D-0.4

Most HTTP clients encode that for you — in JavaScript, build it with new URLSearchParams({ seed, size, noise_base_land: 'oct=6,freq=1,amp=4,offset=-0.4' }).

Every distinct set of commands is a different map, so the first request for one has to render and comes out of your new-maps budget. Repeats are cached like any other map. If your bot lets people tweak sliders live, debounce it.

Command names are validated: an unknown parameter or an unparseable value is a 400 naming the offender, rather than a stock map handed back as though nothing were wrong. The full list of commands and what each one does is in the command guide.

Errors

Errors are JSON: {"error": "bad_size", "message": "…"}. Switch on error, show message.

StatuserrorWhat to do
400missing_seed, bad_seed, bad_size, bad_style, bad_quality, bad_terrain, unknown_parameterFix the request; it will never succeed as sent. unknown_parameter also lists the offending names in an unknown array.
401invalid_keyThe key was not recognised. Omit it to fall back to the anonymous tier.
429rate_limited, generate_rate_limitedWait retry_after seconds. Honour the Retry-After header.
503busy, unavailable, maintenanceTemporary. Retry with backoff.

Using the images

Free to use, including in bots on servers you monetise. One ask: leave the rcemaps.com mark on the image.

Maps are deterministic: the same seed and size always produce the same image, so they are safe to cache forever at your end.

This API is versioned. /api/v1 will not change under you in a breaking way; anything incompatible arrives as /api/v2.