Skip to content
All documentation pages

Getting started with the Minecraft skin render API

How to render a Minecraft skin from one URL: identifiers, render types, first examples, caching advice and error handling for the free Skin Render API.

The URL

Every image the Minecraft skin render API produces has the same address shape. There is no request body, no header you must send and no key.

http
GET https://skinrender.dev/render/<id>/<type>?<parameters>
→ 200 OK, Content-Type: image/png
  • <id> says whose skin to render (identifiers).
  • <type> says what to render: face, head, bust, body, front, back, skin, cape (render types).
  • ?parameters are optional and change size, camera, layers, pose and fallback (parameter reference).

GET /render/<id> without a type redirects to /render/<id>/body, so the shortest possible URL is https://skinrender.dev/render/Notch.

Identifiers

The <id> segment accepts four kinds of value. They are all resolved to a skin texture before rendering.

IdentifierExampleNotes
UUID069a79f444e94726a5befca90e38aaf5
069a79f4-44e9-4726-a5be-fca90e38aaf5
Dashed or undashed, case-insensitive. The stable choice: a UUID never changes, so a stored URL keeps working after the player renames.
UsernameNotch, jeb_1–16 characters, case-insensitive. Resolved to a UUID through Mojang; usernames can be reassigned, so prefer UUIDs in anything you persist.
Texture hashtexture:d5c4ee5c…fb2eb3fThe 64-hex hash from a textures.minecraft.net URL, with or without the texture: prefix. Skips the profile lookup entirely and is cached as immutable.
Default skinssteve, alexThe two built-in skins. Handy for placeholders, tests and docs; they never touch Mojang.

Anything else, such as a 20-character name or a malformed hash, answers 400 with a plain-text reason.

Render types

Each type has its own default size and aspect ratio. The three 3D types (head, bust, body) accept camera and pose parameters; the flat ones are pixel-exact layouts of the texture.

TypeWhat you getDefault
face The 8×8 face with the hat layer on top, scaled with crisp pixels. The classic avatar. 256 px high
head3D The head as a 3D cube, lit and angled, with the hat layer. 256 px high
bust3D Head, torso and arms from the waist up, posable. 256 px high
body3D The full posable player model with every layer and the cape. 512 px high
front A flat, front-on layout of the whole skin, as skin sites show it. 512 px high
back The same flat layout seen from behind, cape included. 512 px high
skin The raw 64×64 texture, upgraded from the legacy 64×32 layout when needed. 256 px high
cape The front of the profile’s cape, flat. 256 px high

Aliases: avatar → face, full → body, portrait → bust.

First examples

Notch rendered with the body type
/render/069a79f444e94726a5befca90e38aaf5/body Full body, default camera (yaw 35°, pitch 12°, orthographic).
jeb_ rendered with the head type
/render/853c80ef3c3749fdaa49938b674adae6/head?size=128 3D head at 128 px, the size most player lists want.
Dinnerbone rendered with the face type
/render/61699b2ed3274a019f1e0ea8c3f06bc6/face?size=64 Flat 8×8 face scaled to 64 px with crisp pixels.
alex rendered with the body type
/render/alex/body?fov=40&pose=sit The default slim skin, sitting, with a perspective camera.

Drop any of those into an <img>. Add width and height attributes matching the requested size so the page does not shift while the image loads.

html
<img src="https://skinrender.dev/render/853c80ef3c3749fdaa49938b674adae6/head?size=128"
     width="128" height="128" alt="jeb_" loading="lazy" decoding="async">

Parameters

Parameters are grouped into 7 families. Every one of them is listed in the parameter reference, which is generated from the same table the parser reads.

  • Output: Size, background and how the file is delivered.
  • Camera: Where the model is viewed from. 3D renders only.
  • Model: Which texture and arm width to render.
  • Layers: Toggle the second skin layer per body part.
  • Lighting: Shading and shadow.
  • Pose: Named poses and per-joint rotations, in degrees by default.
  • Fallback: What happens when a skin cannot be found.

A few rules apply everywhere:

  • Booleans accept 1/0, true/false, yes/no, on/off, or the bare key (?crop means crop=true).
  • Angles are degrees unless units=rad, and they wrap rather than error.
  • size is the height; width follows the type’s aspect ratio unless width or height is given. Nothing exceeds 1024 px per side.
  • Unknown parameters are ignored and listed in the X-Ignored-Params response header. Out-of-range values are a 400.
  • Parameter names are case-insensitive and most have short aliases (w, h, bg, rotate…).

Profile JSON

If you need the resolved profile rather than an image, the same identifiers work on the JSON endpoint:

http
GET https://skinrender.dev/api/profile/Notch

{
  "uuid": "069a79f444e94726a5befca90e38aaf5",
  "name": "Notch",
  "model": "classic",
  "skinUrl": "https://textures.minecraft.net/texture/…",
  "skinHash": "…",
  "capeUrl": null,
  "capeHash": null
}

GET /api/health returns a small JSON status document you can point a monitor at.

Caching advice

Renders are deterministic: the same URL always produces the same bytes. That makes them safe to cache anywhere, and you should.

  • Responses carry Cache-Control: public, max-age=3600, stale-while-revalidate=86400; texture-hash and default-skin renders are immutable.
  • Every response has an ETag. Send it back as If-None-Match and you get a 304 with no body.
  • On our side, profiles are cached for 15 minutes, textures for 24 hours and finished PNGs for an hour in memory. The first request for a player is the slow one (a few hundred milliseconds, because Mojang has to be asked); everything after is served in a few milliseconds.
  • If you render the same players over and over, put a CDN or your own cache in front, or fetch once and store the file.

The details, including Mojang’s rate limit on profile lookups, are on the caching and limits page.

Error handling

Errors are plain text with an appropriate status code, never a PNG that looks like an error.

StatusWhen
400Malformed identifier, unknown render type, or a parameter value outside its range.
404The player does not exist or has no skin, and you asked for default=none. Without it, Steve or Alex is rendered instead and X-Skin-Fallback says so.
502Mojang could not be reached and nothing was cached, again only with default=none.

In an <img> you rarely need to handle any of this: with the default fallback a valid URL always yields an image. When you fetch programmatically, check response.ok and read the body as text on failure.

Next steps