# SteamWebAPI Screenshot API

[Visual guide and image examples](https://www.steamwebapi.com/cs2-screenshot-api)

Render CS2 items from an inspect link using your existing SteamWebAPI API key.
The default response is an AVIF image showing the front with float information
on the [default background image](https://cs2screen.com/assets/cs2screenbg.png),
aligned to the top. Front, back, transparent cutouts, solid background colors,
custom background images, logos and labels are also supported.

**Availability:** included at no extra cost in every package, including Free and
Free+, subject to the package limits.

## Authentication

Send your SteamWebAPI key in the `X-Api-Key` header. The `Key` header and `key`
query parameter are also accepted. Conflicting credentials are rejected.
Screenshot-specific package limits take precedence. If your package does not
define them, its Global limits apply. Explicit zero day/month quotas block access.
First use may take longer while access is initialized.

## Render a screenshot

`GET https://www.steamwebapi.com/steam/api/screenshot`

Send options as query parameters. `game` defaults to `cs2`.

| Parameter | Default | Accepted values |
| --- | --- | --- |
| `url` | Required | Full URL-encoded `steam://` CS2 inspect link, at most 16384 bytes |
| `game` | `cs2` | `cs2` |
| `mode` | `front` | `front`, `back`, `both`; use `both` explicitly to show both sides |
| `width` | `1920` | Integer from 256 to 2048; height scales proportionally. Below 960, use `with_float=false`. |
| `view` | Omitted (default background image) | `transparent` for a cutout; requires `front` or `back` and disables the default background and float information |
| `background_color` | Omitted (default background image) | Solid hex color `#RRGGBB` instead of the background image; URL-encode `#` as `%23` |
| `color` | Omitted | Legacy background color alias: `black`, `blue`, `green`, `orange`, `purple`, `red`, `white`, `yellow`, `gray`, `#RRGGBB` or `#RRGGBBAA`; explicit `background_url` or `background_color` takes precedence |
| `background_url` | Default background image | Custom HTTP(S) image URL, at most 2048 bytes, without credentials or a fragment; incompatible with `background_color` and transparency |
| `background_vertical_align` | `top` | `top`, `center`, `bottom`; requires an image background |
| `logo_url` | Omitted | Custom HTTP(S) logo image URL, at most 2048 bytes, without credentials or a fragment |
| `logo_offset_start` | `top left` | `top left`, `top right`, `bottom left`, `bottom right` |
| `logo_offset_x` | `80` | Integer from 0 to 4096 pixels |
| `logo_offset_y` | `80` | Integer from 0 to 4096 pixels |
| `logo_opacity` | `1` | Number from 0 (invisible) to 1 (opaque) |
| `logo_width` | `400` | Integer from 1 to 1024 pixels |
| `with_float` | `true`; `false` for transparent cutouts | `true`, `false`, `1`, `0`; enabling it requires `width` of at least 960 and cannot be combined with `view=transparent` |
| `item_name` | Original item name | Custom label, at most 64 characters |
| `paint_name` | Original finish name | Custom label, at most 64 characters |
| `format` | `screen` | `screen`, `download`, `base64` |
| `as_base64` | `false` | Compatibility alias: `true` or `1` selects `base64`; `false` or `0` keeps `screen`. An explicit `format` takes precedence. |
| `idempotency_key` | Generated | 1–128 ASCII letters, digits, `.`, `_`, `:`, `-`; alternatively send `Idempotency-Key` |

Use `mode=both` for both sides. `bothsides` is not a mode value.
`view=transparent` cannot be combined with `mode=both`, `background_color`, `color`,
`background_url`, `background_vertical_align` or `with_float=true`. It automatically
omits the background and float information. Use `background_color` without
`background_url` or `background_vertical_align`. Image URLs must be publicly
accessible; they are fetched by the screenshot service. Logo positioning,
opacity and width only affect a supplied `logo_url`.
Unknown and repeated query parameters return HTTP 422.

### Default: front view, background image and float information

```bash
curl --get 'https://www.steamwebapi.com/steam/api/screenshot' \
  --header 'X-Api-Key: YOUR_STEAMWEBAPI_KEY' \
  --header 'Idempotency-Key: YOUR_UNIQUE_REQUEST_ID' \
  --data-urlencode 'url=YOUR_FULL_INSPECT_LINK' \
  --max-time 100 --dump-header screenshot-headers.txt --output screenshot-response
```

No styling parameters are required for this default. The background image and
its top alignment are selected automatically. Use `with_float=false` to
hide float information, or `background_color` to use a solid color instead.

### Custom background and logo

```bash
curl --get 'https://www.steamwebapi.com/steam/api/screenshot' \
  --header 'X-Api-Key: YOUR_STEAMWEBAPI_KEY' \
  --data-urlencode 'url=YOUR_FULL_INSPECT_LINK' \
  --data-urlencode 'color=blue' \
  --data-urlencode 'background_url=https://YOUR_DOMAIN/background.png' \
  --data-urlencode 'background_vertical_align=top' \
  --data-urlencode 'logo_url=https://YOUR_DOMAIN/logo.png' \
  --data-urlencode 'logo_offset_start=top left' \
  --data-urlencode 'logo_offset_x=80' \
  --data-urlencode 'logo_offset_y=40' \
  --data-urlencode 'logo_opacity=0.5' \
  --max-time 100 --dump-header screenshot-headers.txt --output screenshot-response
```

Replace the example image URLs with your public images. `color=blue` is accepted
for compatibility; the explicit `background_url` takes precedence. Without a
background image URL or `background_color`, `color=blue` produces a solid blue
background instead of the default image.

### Front with a transparent background

```bash
curl --get 'https://www.steamwebapi.com/steam/api/screenshot' \
  --header 'X-Api-Key: YOUR_STEAMWEBAPI_KEY' \
  --header 'Idempotency-Key: YOUR_UNIQUE_REQUEST_ID' \
  --data-urlencode 'url=YOUR_FULL_INSPECT_LINK' \
  --data-urlencode 'mode=front' \
  --data-urlencode 'view=transparent' \
  --data-urlencode 'width=1920' \
  --max-time 100 --dump-header screenshot-headers.txt --output screenshot-response
```

For the reverse side, change `mode=front` to `mode=back`.
Check the HTTP status and Content-Type before treating the saved response as
an image: an unfinished render returns JSON with HTTP 202.

### Both sides with a solid background and float information

```bash
curl --get 'https://www.steamwebapi.com/steam/api/screenshot' \
  --header 'X-Api-Key: YOUR_STEAMWEBAPI_KEY' \
  --header 'Idempotency-Key: ANOTHER_UNIQUE_REQUEST_ID' \
  --data-urlencode 'url=YOUR_FULL_INSPECT_LINK' \
  --data-urlencode 'mode=both' \
  --data-urlencode 'background_color=#18324B' \
  --data-urlencode 'with_float=true' \
  --data-urlencode 'width=1920' \
  --data-urlencode 'format=download' \
  --max-time 100 --dump-header screenshot-headers.txt --output screenshot-response
```

Add `item_name` and `paint_name` to customize the labels. To receive JSON
instead of binary image bytes, use `format=base64`.

## Responses and pending renders

| Status | Response |
| --- | --- |
| `200`, `format=screen` | `Content-Type: image/avif`; binary image, displayed inline |
| `200`, `format=download` | `image/avif`; `Content-Disposition: attachment; filename="screenshot.avif"` |
| `200`, `format=base64` | JSON `{"status":"success","image":"data:image/avif;base64,..."}` |
| `202` | JSON `{"status":"pending","job_id":"...","idempotency_key":"..."}` and `Retry-After` |

Accepted requests return the `Idempotency-Key` response header. Responses use
`Cache-Control: private, no-store`.

After HTTP 202, wait for `Retry-After`, then retrieve the result through the
same endpoint and with the same customer key:

```bash
curl --get 'https://www.steamwebapi.com/steam/api/screenshot' \
  --header 'X-Api-Key: YOUR_STEAMWEBAPI_KEY' \
  --data-urlencode 'job_id=JOB_ID_FROM_THE_202_RESPONSE' \
  --data-urlencode 'format=download' \
  --max-time 100 --dump-header screenshot-headers.txt --output screenshot-response
```

`job_id` accepts 1–128 ASCII letters, digits, `_` or `-`. Supply it without
`url` or render options. Only authentication, `game`, `format`, `as_base64` and
`idempotency_key` may accompany it. A still-running job returns HTTP 202 again.
Completed results expire after three hours; save the returned image yourself
if you need it longer. A job ID alone does not grant image access.

## Retries and errors

Choose an idempotency key before the first render and reuse it with unchanged
render options after a timeout. Reusing the same key avoids creating another
job, but each authenticated request still counts towards the screenshot
quota. Use a new idempotency key for a deliberately new request. A single
request has a maximum processing budget of 95 seconds.

Errors return JSON with `status`, `code` and `message`:

```json
{"status":"error","code":"invalid_request","message":"Transparent screenshots require mode=front or mode=back."}
```

| HTTP status | Meaning / action |
| --- | --- |
| `401` | Missing or invalid SteamWebAPI key |
| `402` | Current package does not allow screenshot registration |
| `403` | Screenshot access is disabled |
| `404` | Result does not exist or is not owned by this key |
| `405` | Unsupported method; use GET |
| `406` | Inspect-link format is not supported |
| `409` | Registration or idempotency conflict; check the message and render options |
| `410` | Stored result expired; request a new render |
| `422` | Invalid parameters or incompatible options |
| `429` | Quota, capacity or access-initialization limit; respect `Retry-After` |
| `502` | Invalid screenshot response; retry with the same idempotency key |
| `503` | Endpoint disabled or temporarily unavailable; respect `Retry-After` when present |

## Screenshot usage

`GET https://www.steamwebapi.com/steam/api/screenshot/usage`

Use the same authentication as for rendering. This endpoint initializes access
for an eligible key if necessary. Load usage on demand; do not poll it for
every screenshot. Respect `Retry-After` if it returns HTTP 429.

```json
{
  "status": "success",
  "active": true,
  "limits": {"minute": 100, "day": 1000, "month": 10000},
  "usage": {"minute": 1, "day": 25, "month": 240, "total": 500, "blocked": 0},
  "timezone": "UTC",
  "period": "calendar",
  "unit": "authenticated_requests"
}
```

These numbers are examples; actual limits depend on your configured screenshot
quota. A `null` limit means unlimited. Day and month counters reset at UTC
calendar boundaries. Result retrieval and render retries also count.
`total` covers the retained usage history, not necessarily lifetime usage.
These counters are separate from the ordinary SteamWebAPI credit balance.

## Existing integrations

`GET /steam/api/float/screenshot` is a compatibility URL for
`/steam/api/screenshot`. Caddy routes it internally to the same screenshot
proxy, preserving query parameters and authentication headers. There is no
client redirect and no separate Float Screenshot renderer.

Both URLs return the same AVIF output, default to `mode=front`, and use the
same screenshot quotas. The previous PNG layout and ordinary credit billing
are no longer available. Clients that expect PNG must accept `image/avif`.
`format=screen|download|base64`, `color`, `background_url` and `logo_*` are
supported. The old `as_base64=1` option maps to `format=base64` unless an
explicit `format` is supplied. Use `/steam/api/screenshot` for new integrations.
