# via.placeholder.com
> Free placeholder images, avatars, photos, QR codes, test-safe barcodes and fictional brand images by URL. No sign-up, no API key. The same URL always returns the same bytes (cached for a year). For mockups, prototypes, tests and demos only: never ship these URLs or files to production, and run placeholder-check in CI (https://tools.placeholder.com/placeholder-check).
All endpoints: GET/HEAD, CORS `*`, header `X-Placeholder: via.placeholder.com` on every image. Always set `width` and `height` on ``.
## Images (placehold.it syntax)
```
https://via.placeholder.com/{size}[@{scale}x][/{bg}[/{fg}]][.{format}][?text={text}]
```
- size: `150` (square) or `600x400` (width x height). 1..4000 px per side. Larger returns a 200 image reading "Max size is 4000 x 4000".
- bg, fg: 3/6-digit hex WITHOUT `#` (`ff6600`, `09f`) or a CSS colour name (`navy`). Defaults: bg `cccccc`, fg `969696`. Unknown colours fall back to the default.
- format: `png` (default), `jpg`/`jpeg`, `gif`, `webp`, `svg`. The extension may go on any segment. `avif`: see below.
- text: URL-encoded, max 120 characters. Default text is the size, e.g. "600 x 400".
- retina: `@2x` or `@3x` (also `@1.5x`; clamped to 1..3) on the SIZE segment only: `/600x400@2x` is 1200x800 pixels with the same layout and text. Before or after the extension (`/600x400@2x.png`, `/600x400.png@2x`). Output capped at 4000 px per side (scale lowered to fit). `?dpr=` is IGNORED on these classic URLs; use the suffix. SVG keeps the logical viewBox with width/height multiplied.
- avif: put `.avif` on the size segment (`/600x400.avif`, `/600x400.avif/ff6600/fff`) or anywhere once the size carries a scale (`/600x400@2x/ff6600/fff.avif`). `/600x400/ff6600/fff.avif` is NOT AVIF: it returns a PNG with the default text colour (legacy URL, frozen bytes). Above 2.1 MP (e.g. `1200x800@2x`) AVIF is served as WebP, `Content-Type: image/webp`.
Examples:
- https://via.placeholder.com/150
- https://via.placeholder.com/600x400
- https://via.placeholder.com/600x400/ff6600/ffffff
- https://via.placeholder.com/600x400.svg
- https://via.placeholder.com/600x400.webp?text=Hero+image
- https://via.placeholder.com/1200x630/1c1d19/ecf34d.jpg?text=Open+Graph+image
- https://via.placeholder.com/600x400@2x.webp
- https://via.placeholder.com/600x400.avif
These classic images have no embedded marker (their bytes are frozen; retina PNG/JPEG/GIF/WebP/SVG neither), so downloaded copies are not detectable: link to them, don't download them. Exception: classic AVIF carries the marker.
## Avatars
```
https://via.placeholder.com/avatar/{name}[@{scale}x][.{format}][?size=&shape=&style=&bg=&fg=&seed=&dpr=]
```
- name: URL-encoded full name -> initials (`Anna%20Svensson` -> "AS"). Slugs (`anna-svensson`) and e-mail local parts work. Or `?name=`.
- format: `png` (default), `svg`, `webp`, `jpg`, `gif`, `avif` (keeps transparent corners).
- size: 16..512 (clamped), default 128. Also `?s=` or a path segment `/avatar/128/{name}`.
- retina: `@2x`/`@3x` (also `@1.5x`) at the end of any segment (`/avatar/Anna%20Svensson@2x.png`, `/avatar/64@2x/Anna`) or `?dpr=1..3` (suffix wins). Output = size x scale px, capped at 512. E-mail names (`anna@x.se`) are not scales.
- shape: `circle` (default), `square`, `rounded`.
- style: `initials` (default for names), `shapes`, `identicon`, `silhouette`; also as a path segment: `/avatar/identicon/{seed}`.
- bg, fg: hex (with or without `#`) or CSS colour name. Without fg, text colour is chosen for contrast.
- seed: any string; picks colours/pattern. Default: the name as written. Use a stable user ID.
- Never errors. Never draws a human face. Descriptor slugs (`woman-40s-smiling`, `u/42`) get abstract shapes; generic words (`default`, `user`) get a silhouette.
Examples:
- https://via.placeholder.com/avatar/Anna%20Svensson.png
- https://via.placeholder.com/avatar/Anna%20Svensson.svg?size=64&seed=user-1842
- https://via.placeholder.com/avatar/Anna%20Svensson.png?bg=1c1d19&fg=ecf34d&shape=rounded
- https://via.placeholder.com/avatar/identicon/user-42.png
- https://via.placeholder.com/avatar/default.png
- https://via.placeholder.com/avatar/Anna%20Svensson@2x.png
- https://via.placeholder.com/avatar/Anna%20Svensson.avif
## Photos
```
https://via.placeholder.com/photo/{subject-words}/{width}x{height}[@{scale}x][.{format}][?seed=&grayscale&blur=&dpr=]
```
- subject words: separated by `-`, `_`, `+` or spaces; several segments allowed (`food/pizza`). Synonyms and plurals are understood. Also `?q=`. No words = any photo.
- size: `1200x800`, one number for a square, or `/{w}/{h}`. Also `?w=` `?h=`. Default 1200x800. Max 2000 px per side; larger requests are scaled down keeping the aspect ratio.
- format: `jpg` (default), `webp`, `png`, `avif`. AVIF above 2.7 MP (e.g. 2000x1500) is served as WebP, `Content-Type: image/webp`.
- retina: `@2x`/`@3x` (also `@1.5x`) at the end of any segment, or `?dpr=1..3` (suffix wins). Same crop, more pixels; output capped at 2000 px per side (so `1200x800@2x` is 2000x1333). Sources are at most 1600 px; larger outputs are upscaled.
- seed: another equally good match, still fixed per URL. `grayscale`: flag. `blur`: 1..10 (bare `blur` = 2).
- Segments can be in any order. Unknown subjects return a grey placeholder of the requested size with the words on it (still 200, no `X-Photo-Id` header).
- Response headers: `X-Photo-Id`, `X-Photo-License` (CC0 / public domain), `Link: ; rel="license"`.
- Available subjects: https://via.placeholder.com/photo/tags (JSON). Credits: https://via.placeholder.com/photo/credits
Examples:
- https://via.placeholder.com/photo/coffee/1200x800
- https://via.placeholder.com/photo/mountain-lake/800x600.webp
- https://via.placeholder.com/photo/cafe-interior/600x400?grayscale
- https://via.placeholder.com/photo/coffee/800x600?seed=3
- https://via.placeholder.com/photo/coffee/800x600@2x.webp
- https://via.placeholder.com/photo/coffee/1200x800.avif
## QR codes
```
https://via.placeholder.com/qr/{url-encoded text}[.png|.svg|.webp|.gif|.jpg][?size=&ecc=&margin=&fg=&bg=&scale=]
https://via.placeholder.com/qr.png?text={text} https://via.placeholder.com/qr?data={text}&format=svg
```
- text: everything after `/qr/` (slashes included) minus a trailing image extension; `?text=`/`?data=` win. Max 1024 UTF-8 bytes, else 400. No text = `https://placeholder.com/`. Percent-encode URLs: an unencoded URL's query keys that clash with ours (size, color, margin...) are taken as ours.
- format: `png` (default), `svg`, `webp`, `gif`, `jpg`. Other extensions (avif too) -> png.
- size: 16..2000, default 200 (exact square; grows if the code doesn't fit). `scale`: 1..50 px per module instead.
- ecc: `L`, `M` (default), `Q`, `H`. margin: 0..20 modules, default 4. fg/bg: hex, CSS name or `r-g-b`; `bg=transparent` for png/svg/webp/gif.
- Header `X-QR-Version` (e.g. `2-M`). Alias `/qrcode/...`; Google Charts params `chl`, `chs`, `chld` work.
Examples:
- https://via.placeholder.com/qr/https%3A%2F%2Fexample.com%2F
- https://via.placeholder.com/qr/hello.svg
- https://via.placeholder.com/qr.png?text=Hello%20world&size=300
- https://via.placeholder.com/qr/hello?ecc=H&margin=2&fg=1c1d19&bg=ecf34d
## Barcodes (test-safe)
```
https://via.placeholder.com/barcode/{type}/{value}[.png|.svg|.webp|.gif|.jpg]
https://via.placeholder.com/barcode/{type}[?seed={s}&prefix=company|region|demo] a test-safe code
https://via.placeholder.com/barcode/{type}/test.json?count={1..100}&seed={s} list of test-safe codes
```
- type: `ean13`, `upca`, `ean8`, `itf14`, `gs1-128`, `code128`, `code39` (aliases: ean, upc, gtin13, gtin12, gtin14, itf, c128, c39, ean128...). `/barcode/{digits}` guesses by length (8 EAN-8, 12 UPC-A, 13 EAN-13, 14 ITF-14, else Code 128). `/barcode/qr/{text}` = QR.
- value: numeric types take the value without its check digit (computed) or with it. A WRONG check digit = 400 error image + `X-Placeholder-Error`; `?check=fix` corrects, `?check=keep` renders it (header `X-Barcode-Warning`). GS1-128: `(01)09521234500001(10)ABC`. Code 39: `?check=mod43`.
- No value (or `test`, `random`, `sample`, `demo`) = a test-safe code from GS1 ranges no real product carries: EAN-13 prefix 04 (company RCN, default), 02/20-29 (`prefix=region`; may scan as a priced variable-weight item), 952 (`prefix=demo`); UPC-A number system 4 (or 2); EAN-8 prefix 2 (or 952); ITF-14 and GS1-128 on 952. Code 128/39: `TEST-` + 6 digits. Source: GS1 General Specifications R26.0, Table 1-4/1-5, 2.1.11. Header `X-Barcode-Test` names the range.
- Options: `scale` 1..10 px per bar (default 2), `width` (exact width), `height` 10..1000, `hrt=0` hides digits, `margin` (quiet zone, never below the symbology minimum), `bearer=0` (ITF-14), `fg`, `bg`.
- Headers: `X-Barcode-Type`, `X-Barcode-Value`. Errors are 400 images cached a day.
- Never put real product GTINs in tests; use these.
Examples:
- https://via.placeholder.com/barcode/ean13
- https://via.placeholder.com/barcode/ean13?seed=7
- https://via.placeholder.com/barcode/ean13/048192616039
- https://via.placeholder.com/barcode/gs1-128/(01)09521234500001(10)ABC
- https://via.placeholder.com/barcode/code128/HELLO-123.svg
- https://via.placeholder.com/barcode/ean13/test.json?count=10&seed=7
## Brand images
```
https://via.placeholder.com/brand/{slug}/{asset}.{svg|png|webp|jpg|ico}[?theme=&mono=&bg=&size=&h=&w=]
```
- Fictional brands; the kit (JSON, CSS tokens) is at https://data.placeholder.com/brands/{slug}. Curated slugs: https://data.placeholder.com/brands. Any name-like slug becomes the name (`quillmere-labs` -> "Quillmere Labs"); other slugs (`42`, `test`, real brand names) get a generated fictional name.
- assets: `logo` (mark + wordmark; `?h=` 16..1024, default 128, or `?w=`; `?layout=stacked`), `logomark` (`?size=` 16..1024, default 256), `favicon` (`.ico` = 16/32/48; `?size=` 16..512, default 32; `apple-touch-icon.png` = 180), `og` (1200x630 social card, `?theme=brand|light|dark`), `palette` (1200x630 swatch sheet).
- common: `theme=light|dark`, `mono=1`, `bg=transparent|white|brand|light|dark|{hex}`. Aliases: wordmark/lockup -> logo; mark/icon/symbol -> logomark; social/opengraph/twitter-card -> og; colors/swatches -> palette; digits in the file name set the size (`android-chrome-192x192.png`). Unknown names -> logo; unknown extensions (avif too) -> png. Never errors.
- Fonts: https://via.placeholder.com/brand/_fonts/{file} (SIL OFL).
Examples:
- https://via.placeholder.com/brand/brightfjord/logo.svg
- https://via.placeholder.com/brand/brightfjord/logo.png?h=64&theme=dark
- https://via.placeholder.com/brand/brightfjord/favicon.ico
- https://via.placeholder.com/brand/brightfjord/og.png
- https://via.placeholder.com/brand/quillmere-labs/logomark.svg
## Detectability
Every avatar, photo, QR code, barcode and brand image file (except brand `.ico` favicons), and every classic AVIF, embeds the text "Placeholder image from via.placeholder.com - replace before shipping" (PNG tEXt, JPEG COM, GIF comment, WebP/AVIF XMP, SVG comment + `data-placeholder="via.placeholder.com"`). placeholder-check finds these files and any placeholder URL in a build:
```
curl -fsSL https://tools.placeholder.com/check/placeholder-check | python3 - dist
```
## Docs
- [Images](https://tools.placeholder.com/images): full syntax and headers
- [Avatars](https://tools.placeholder.com/avatars): styles, aliases, personas
- [Photos](https://tools.placeholder.com/photos): subjects, cropping, credits
- [QR codes and barcodes](https://tools.placeholder.com/qr): options, test-safe GS1 ranges, check digits
- [Brand kits](https://tools.placeholder.com/brands): kit JSON, tokens.css, logos, favicons, social cards
- [CI check](https://tools.placeholder.com/placeholder-check): placeholder-check options, GitHub Actions, GitLab, pre-commit
- [Placeholder data](https://data.placeholder.com/llms.txt): people, mock REST API, company dataset, brand kits, fixtures with answer keys, text, safe test values
- [Everything](https://tools.placeholder.com/llms-full.txt): also dummy files (files.placeholder.com) and HTTP test endpoints (http.placeholder.com)