← cs2inspect.skin

Embed API

Put any CS2 skin on your own page, in 3D, with the stickers, charm, name tag, float and pattern seed you choose. It is an <iframe> whose look is decided by its URL — no SDK, no build step, nothing to install.

Playground

Turn every option on and off and watch the frame change. The tag under it is exactly what produces what you see — copy it onto your page and swap in your key. Each switch names the parameter it sets.

Drag to orbit. In first person, click fires, R reloads, G draws the weapon again and F inspects. The chequerboard is the page behind the embed: with no bg the frame is genuinely transparent, not black.

Quick start

One tag. Replace the key with your own (see below) and the item with any skin on the site — the two path segments are the same ones in our own URLs, so cs2inspect.skin/ak-47/redline becomes item=ak-47/redline.

<iframe
  src="https://cs2inspect.skin/embed?key=pk_live_YOURKEY&item=ak-47/redline&wear=0.18&seed=661&spin=6"
  width="600" height="400" frameborder="0" title="AK-47 | Redline"></iframe>

The frame is transparent by default, so it sits on your own background. Give it whatever size you like; the weapon is framed to fit whatever box it lands in.

Naming a skin

Three ways, whichever your data already looks like.

item=ak-47/redline

The site's own two slugs: weapon, then skin. item=ak-47 on its own shows the bare weapon.

name=AK-47 | Redline (Field-Tested)

The exact Steam market name, exactly as a marketplace holds it. Everything around the skin's own name describes the copy rather than the skin, so it is unpicked for you: ★ and Souvenir are dropped, the (Field-Tested) suffix is dropped because wear says it exactly, and StatTrak™ turns the counter on unless your st says otherwise. So ★ StatTrak™ Karambit | Doppler (Factory New) just works.

weapon=ak47&paint=282

The model key and the paint index, as they appear in an inspect link. Best if you already parse inspect links; paint left out means the bare weapon.

Backgrounds and the two corners

The background is invisible unless you ask for one

There is nothing to switch on: with no bg the frame is fully transparent and your own page shows through it, whatever colour, gradient or image is back there. Set bg only when you want the embed to paint its own — bg=0b0d12, bg=white, bg=rgb(20,22,30). bg=transparent says the default out loud, which is worth doing if you are generating these URLs from a template.

Our wordmark: you choose how it looks and where it sits

It sits bottom left by default. logo=icon shrinks it to the mark alone, logo=minimal drops the dark pill behind it for pages that are dark anyway, and logopos=br, tl or tr moves it to another corner. The embed is free and every load serves a weapon model and several megabytes of texture off our bandwidth; the credit is what pays for that, so on the Basic plan it cannot be removed — logo=none is ignored and the default mark shows. Accounts on the Premium plan can use logo=none to remove it from every embed made with their keys.

The other bottom corner: the name card, and you can remove it

The skin's name, its float and its seed, in whichever bottom corner the wordmark is not in. Useful on a page that does not say those anywhere else, noise on a product page that already does. card=0 and it is gone. The controls move the same way, to the top corner the wordmark leaves free.

Every parameter

Parameter Default What it does
item — weapon/skin slugs, e.g. awp/dragon-lore.
name — The full market name, instead of item.
weapon, paint — Model key and paint index, instead of item.
wear 0.06 The float, 0–1. Clamped to the skin's own legal range.
seed 1 Pattern index, 0–1000. Decides which part of the artwork lands where.
st 0 StatTrak™ module on the weapon.
nametag none Name tag text, up to 20 characters.
stickers none See stickers and charms.
charm none index or index:seed.
bg transparent transparent (the default — your own page shows through), a hex colour (0b0d12), an rgb() or a colour keyword.
spin 0 Turntable speed in degrees per second. Pauses while someone is dragging.
card 1 card=0 removes the little name card in the bottom-left — the skin name, float and seed.
interactive 1 interactive=0 stops dragging and zooming.
view item view=hands shows the weapon held in first person, as in game. Click fires (hold for automatic weapons), right click is a knife's heavy attack, F inspects.
gloves — Gloves worn in first person: sport-gloves/vice (our page slugs) or the market name Sport Gloves | Vice. Absent or none: the agent's own. Change live with view.setGloves().
glovewear 0 The gloves' float, 0–1, e.g. glovewear=0.15. Live: view.setGloves("sport-gloves/vice", 0.15).
scene none A background from our maps, lit by that map's lights: vanity (warehouse), dust2, mirage, inferno, nuke, overpass, ancient_day, ancient_night, anubis, baggage, cache, italy, office, train, vertigo.
controls 0 controls=1 shows buttons for the view (rotate / first person), inspect and, with a scene, a background picker.
ui 1 ui=0 starts with the name card and controls hidden. H, the Hide UI button or view.setUi() toggles them. The wordmark always stays.
accent D4FF4A Colour of the loading indicator and the active control. Hex (no # needed), rgb() or a colour name.
loader bar Loading indicator: bar, spinner, dots or none.
logo full How the wordmark looks: full, icon or minimal. none removes it, on the Premium plan only; on Basic it is ignored. See the corners.
logopos bl The wordmark's corner: bl, br, tl or tr. The name card and controls take the corners it leaves free. In embed.js also accepted as logoPosition.
key — Your embed key. Required on every site but ours.

A parameter this build has never heard of is ignored rather than refused, and so is a sticker that is not in the catalogue. An embed that drops one sticker is a small disappointment; one that renders an error box on your page because we shipped something new is not.

Stickers and charms

A sticker is slot:index, comma-separated. The slot is a position on the weapon counted from 0; the index is the sticker's own number, the one in its inspect link.

stickers=0:5032,2:4501

Four optional numbers place it exactly, in the order you would say them — across, down, turn, wear: slot:index:x:y:rotation:wear. x and y are the game's own sticker offsets from the slot's centre (the values in an inspect link; 0 is centred), rotation is in degrees, and wear is the sticker's scrape, 0 (pristine) to 1. Leave all four out and the sticker sits in the slot's default spot.

stickers=0:5032:0.02:-0.01:12:0.1
charm=4123:661

The quickest way to get one of these right is to build it on the site — open a skin, place the stickers, then API → Copy iframe in your account menu. The snippet is the build on screen.

Changing it without reloading

Optional, and only worth it if the embed has to react to something on your page — a skin picker, a float slider, a row of stickers being chosen. The loader is 3 KB and has no dependencies.

<div id="viewer" style="height:400px"></div>
<script src="https://cs2inspect.skin/embed.js"></script>
<script>
  var view = CS2Inspect.embed("#viewer", {
    key: "pk_live_YOURKEY",
    item: "ak-47/redline",
    wear: 0.18,
    spin: 6,
  });

  view.on("ready", function (e) { console.log("showing", e.item); });
  view.on("error", function (e) { console.warn(e.reason, e.message); });

  // Later — only the fields you pass change.
  view.update({ wear: 0.41, stattrak: true, stickers: [{ slot: 0, index: 5032 }] });
  view.resetView();
</script>

CS2Inspect.url(spec) returns the embed URL for a spec without creating a frame, if you would rather render the iframe yourself.

Without the loader

The loader is a wrapper over postMessage. Anything it does you can do directly:

frame.contentWindow.postMessage(
  { type: "cs2embed:set", spec: { wear: 0.41, spin: 0 } },
  "https://cs2inspect.skin",
);

window.addEventListener("message", function (e) {
  if (e.data && e.data.source === "cs2inspect-embed") console.log(e.data.type, e.data);
});

Messages in: cs2embed:set (any parameter above, including view and scene), cs2embed:reset, cs2embed:inspect, cs2embed:fire (alt: true for the secondary attack), cs2embed:ping. With embed.js: view.setView("hands"), view.setScene("dust2"), view.inspect(), view.fire(), view.setUi(false). Messages out, all carrying source: "cs2inspect-embed": ready (with the item it resolved), updated, view (the view changed), error and pong.

Getting a key

  1. Sign in at cs2inspect.skin — Steam or an email code.
  2. Open the account menu and choose API.
  3. New key, name it, and list the sites it may be embedded on: example.com, or *.example.com for a domain and everything under it. Ports are ignored, so localhost covers your dev server on any port.
  4. Paste the key into the embed URL as key=….

The key is public, and that is fine

It travels in the HTML of every page that frames the viewer, so anyone can read it. What limits it is the list of sites next to it, not secrecy — and nothing behind it is private: these are the same skins on our own public pages. Treat it as a name, not a password. If you would rather it stopped working, switch it off in the API panel.

Fair use

Every embed loads a weapon model and its textures from us, which is megabytes per skin, so asset requests are metered per visitor. Ordinary browsing never notices; a page that mounts fifty embeds at once will. Load them lazily as they scroll into view — the JS loader already sets loading="lazy".

When it does not work

The frame says what is wrong and what to do about it, and posts the same thing to your page as an error message with a reason:

no_key No key in the URL, on a site that is not ours.
bad_key No such key. Check it against the API panel.
revoked The key was switched off by its owner.
origin_not_allowed This site is not on the key's list. Add it in the API panel.
no_origin The page was opened directly instead of being framed.
unknown_item Nothing in the catalogue answers to that name, slug or paint index.
no_model The skin is real but its model could not be loaded. Usually temporary.
rate_limited Too many embeds from one visitor at once. Clears by itself.