¯\_(ツ)_/¯shrug.pics

Docs

Drop a URL into your mockup. The image renders. The URL is the API.

The basics

<img src="https://shrug.pics/600/400">
<img src="https://shrug.pics/600/400.png">
<img src="https://shrug.pics/avatar/96">

And here is each rendered live, on this page:

300 by 200 placeholder96px avatar placeholder728-wide banner placeholder

Routes

Width and height are integers between 8 and 4000. PNG output is rasterized via resvg-wasm.

Query parameters

Going paid

Two ways to send your key with a request:

1. Domain allowlist (preferred)

Register your domains in the dashboard (coming soon). Our server matches the Referer header from the requesting page. Your HTML stays clean — no key in the URL.

# Just embed normally — same URL as free tier
<img src="https://shrug.pics/600/400">

Wildcards work for one subdomain layer: *.acme.com matches staging.acme.com but not acme.com (register both if you want both) and not a.b.acme.com. localhost matches any port.

2. Query param key

For headless / scripted use, when there's no Referer:

curl -O "https://shrug.pics/600/400?key=shp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Heads up: query params are visible in HTML source, browser history, and intermediary logs. Prefer the domain allowlist for production embeds.

What changes when you're paid

Heads up: these networks won't work for direct image embedding — Google AdSense / AdX, Meta Audience Network, OpenRTB exchanges. ToS prohibits server-side rendering or proxying. For client-side networks, the /iframe/ route serves their snippet inside our domain.

Click + impression tracking

Free renders include an HMAC-signed /c/:token click link and record an impression server-side. Paid renders are clean, deterministic, and cacheable for 24h.