Probe remote image dimensions (width × height) from just a URL — without downloading the image.
Image formats keep their dimensions in the file header, so Dims
fetches only the first ~128 KB via an HTTP Range request, parses the
JPEG / PNG / WebP / GIF header, and discards the bytes. Milliseconds and
a few KB per image instead of megabytes.
Dims.probe("https://cdn.example.com/page1.jpg")
#=> %{width: 800, height: 8000}
Dims.probe_all(urls)
#=> [%{url: ..., width: 800, height: 1200}, ...] # input order preservedUseful anywhere you deal with images you don't host: reserving layout
space (aspect-ratio, <img width height>) before anything loads,
link previews, gallery imports, comic/manga readers deciding page
layouts, CMS ingestion.
Install
def deps do
[
{:dims, "~> 0.1"}
]
endBatch probing, built for the real world
- Parallel —
probe_all/2sweeps the list with bounded concurrency (default 8), preserving order. - Median backfill — a probe that fails or times out gets the median dimensions of its successful siblings, not a constant fallback. Image sets (chapter pages, galleries) are near-uniform, so the estimate is close — and relative layouts built from the results never explode.
- Sampling —
probe_sampled/2probes ~20 evenly-distributed URLs of a huge list and median-fills the rest: accuracy within a percent or two for uniform sets at ~25× less traffic.probe_auto/2switches between full and sampled by list length (default threshold 80). - Caching — results cache in ETS with a 30-day TTL (a URL's bytes
don't change, so its dimensions don't either). Bypass per call with
cache: false.
Options
Dims.probe(url,
headers: [{"referer", "https://source.example/"}], # CDNs that check referers
headers_fun: &MyApp.headers_for/1, # per-URL headers
probe_bytes: 131_071,
receive_timeout: 8_000,
cache: true,
cache_ttl: :timer.hours(24 * 30)
)Batch calls also take :max_concurrency, :sample_size, and
:full_threshold.
Parsing bytes you already have
Dims.Parser.parse/1 is the pure header parser — hand it the leading
bytes of an upload or a cached chunk and get %{width:, height:} back
with no I/O.
Formats
JPEG (all SOFn markers, so progressive too), PNG, WebP (VP8 / VP8L / VP8X), GIF (87a/89a).
License
MIT