image-meta
image-meta
Detect image type and size using pure JavaScript. It has no dependencies and works in Node.js, browsers and other runtimes.
Usage
import { imageMeta } from "image-meta";
const res = await fetch(url);
const data = new Uint8Array(await res.arrayBuffer());
const meta = imageMeta(data);
// => { type: "png", width: 123, height: 456 }
In Node.js, a Buffer works as input because it is a Uint8Array:
import { readFile } from "node:fs/promises";
import { imageMeta } from "image-meta";
const meta = imageMeta(await readFile("./image.jpg"));
The type is detected from the file contents, not the file extension.
Result
type ImageMeta = {
type?: string; // detected format, e.g. "png"
width: number; // of the largest image when there are several
height: number;
orientation?: number; // EXIF orientation (jpg)
images?: Omit<ImageMeta, "images">[]; // all embedded images (ico, cur, icns)
animated?: boolean; // animation or image sequence (gif, png, webp, avif, heic, jxl)
pages?: number; // number of frames or pages (gif, png, webp, tiff)
};
Animation and pages
animated and pages are read from the headers without decoding the image, and are left undefined when they can't be found cheaply (for example in a truncated file). A single frame is not reported as animated. For tiff, every directory counts as a page, including thumbnails and reduced-resolution images (e.g. in camera raw files).
| Format | animated |
pages |
|---|---|---|
| gif | more than one frame | number of frames |
| png (APNG) | acTL chunk before IDAT |
acTL frame count |
| webp | VP8X animation flag |
number of ANMF chunks |
| avif / heic | sequence brand (avis, msf1, …) and a moov box |
- |
| jxl | have_animation in the image metadata |
- |
| tiff | - | length of the IFD chain |
These values are best-effort hints, useful for UX and processing decisions (keeping an animation when converting, skipping a step for single-frame images, showing a frame count). They are not reliable for security decisions such as size or resource limits: image-meta parses headers on its own, so for malformed or crafted files its answer can differ from what a decoder will do. Ask the decoder that will process the file when you need a guarantee.
Error handling
imageMeta throws an error if the input is not a Uint8Array, the format is unsupported, or the data is invalid. Wrap calls that take untrusted input in try/catch:
try {
const meta = imageMeta(data);
} catch {
// Not a supported image
}
Supported formats
avif, bmp, cur, dds, gif, heic, icns, ico, j2c, jp2, jpg, jxl, ktx, png, pnm, psd, svg, tga, tiff, webp
Development
- Clone this repository
- Install the latest LTS version of Node.js
- Enable Corepack using
corepack enable - Install dependencies using
pnpm install - Run interactive tests using
pnpm dev
See AGENTS.md for the project layout and how to add a new format.
License
Made with
Based on image-size by Aditya Yadav and contributors.
Published under MIT License.