Library / SDK
mattiasw/ExifReader avatar
mattiasw/ExifReader

ExifReader: reading image metadata without a native dependency

A JavaScript Exif info parser.

1,004 stars107 forksJavaScriptMPL-2.0

At a glance

What is it?
ExifReader is a JavaScript library that parses JPEG, JPEG XL, TIFF, PNG, HEIC, AVIF, WebP and GIF files and returns their Exif, IPTC, XMP, ICC and MPF metadata as plain objects, with TypeScript definitions and a CLI. Its selling point is a build that can be as small as about 9 KiB compressed.
Who is it for?
Adopt ExifReader if you need to read photo metadata in a browser or in Node without a native module, you want the full metadata set rather than a few tags, and you care about bundle size. Do not adopt it for image processing beyond metadata, since it parses headers and tags and does not decode pixels, and do not rely on it for a format or tag it has not been tested against, since several entries in the support table are partial by the maintainer's own account.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Metadata only, and that is the whole scope

ExifReader is a JavaScript library that parses image files and extracts the metadata, and it can also extract an embedded thumbnail. It can be used either in a browser or from Node. The supported file types are JPEG, JPEG XL, TIFF, PNG, HEIC, AVIF, WebP and GIF, and the metadata families it reads are Exif, IPTC, XMP, ICC, MPF and more depending on file type. The important word in that list is parses. This is not an image processing library, it does not decode pixels into a bitmap, and it does not resize, convert or compress images. What it does is read the container, find the metadata blocks and hand you structured objects. That scope is exactly what a photo upload service, a geotagging feature or a metadata stripper needs, and it is also what makes the library usable in a browser, where decoding a JPEG by hand would be a large amount of work for a job nobody asked for. The author is Mattias Wallander, and the licence is MPL-2.0, which is the file-level copyleft licence and a common choice for a JavaScript library of this kind.

The support table's footnotes are the real documentation

The README prints a support matrix of file type against metadata family, and the footnotes under it are where the honest detail lives. MakerNote support covers manufacturers' proprietary tags, with some Canon-specific and Pentax-specific tags added. Photoshop tags are partial by deliberate choice, because they are very different from other tags and need a lot of extra code, so only ClippingPathName and PathInformation are currently supported, and the project invites an issue if something should be supported. For JPEG XL, metadata is often but not always encoded with Brotli compression, which is supported in some environments when using async: true, and the table marks MPF as not applicable for the format because a JPEG recompressed to JPEG XL keeps its MPF segment only in its JPEG reconstruction data, which ExifReader does not read. IPTC for the newer formats is read from the Exif data, where the IPTC-NAA and ICC_Profile tags can carry it, in the same way as for TIFF files, because HEIC/HEIF, AVIF and WebP define no IPTC block of their own, and the ICC profile inside a JPEG XL codestream is not read. GIF is the outlier, with only image details available, which are the image width and height read from the image header. If a feature matters to you, the footnotes tell you whether it is there in full, in part, or not at all.

Two ways to load a file, one synchronous and one not

The usage section offers two entry points and the difference is in who loads the bytes. Either ExifReader loads the image file for you, or you load the file yourself first and pass in the file buffer, and the main difference is that the first is asynchronous while the second is synchronous unless specified. The asynchronous form is the one most people will use:

javascript
const tags = await ExifReader.load(file);
const imageDate = tags['DateTimeOriginal'].description;
const unprocessedTagValue = tags['DateTimeOriginal'].value;

The two lines that read the same tag are worth pausing on, because they show the shape of every value the library returns. The description field holds the human-readable rendering of the tag, in this case a formatted date, and the value field holds the raw value as the file stored it. Every tag behaves this way, so an application that wants to display a tag uses description and an application that wants to compare or index uses value. The file argument for load is a file object, a blob, an ArrayBuffer or a URL, and the buffer form is the one that lets you read metadata from a file you already have in memory without a second round trip. Type definitions for TypeScript are included in the package, at exif-reader.d.ts.

Bundle size is treated as a feature

Two options in the library exist to keep the payload small, and both are documented as headline features. The first is the length: 'auto' option, which makes ExifReader read only the bytes that contain metadata. The project puts a number on it, claiming well under 1 ms per file for typical phone JPEGs and over 95% less bandwidth, and those are the maintainer's own measurements rather than an independent benchmark, but the direction of the claim is mechanically sound, since a phone JPEG usually has a large image payload and a comparatively small metadata block. The second is the custom build configuration, where the library is highly and easily configurable and the resulting bundle can be as small as about 9 KiB Brotli-compressed if you are only interested in a few tags such as date or GPS values. That is a meaningful number for a mobile web application, and it is the reason to choose this library over a general purpose image library that pulls in a decoder you do not need. The trade is that a custom build means you declare up front which tags you care about, and a tag you did not include is simply absent rather than empty.

Module systems, the exports map, and a CLI

The library ships in a lot of shapes, which reflects a project that has been around long enough to be used in every kind of build. The README lists ES module syntax with a default import, a note that TypeScript and Angular sometimes have problems with the default export, in which case a namespace import is the workaround, then CommonJS with require, AMD with requirejs, and a plain script tag. It also states that the library supports the ESM, AMD, CommonJS and globals module formats and can therefore be used from Webpack, RequireJS, Browserify and Node. The package.json shows how that is arranged in the current version, with main pointing at the built dist/exif-reader.js, module pointing at the source src/exif-reader.js, sideEffects set to false, and an exports map that routes browser, node, module, import, require and default to the appropriate file, plus wildcard entries for src/* and dist/*. The newest release, v4.50.0, is described as adding that package exports map and Node file loading in ES module bundles, so the module resolution story has just been reworked. There is also a command line entry, with the bin field mapping exifreader to bin/cli.js, and the repository holds a bin/ directory, a Dockerfile for testing custom builds, examples for AMD, ESM, globals, Node and a plain HTML page, Cypress for browser tests, Mocha for unit tests, and a Husky setup for git hooks.

Where ExifReader is the wrong tool

Four boundaries are clear. The first is that metadata is all it does. If you need to resize, convert, crop or re-encode an image, you need a different library, and one that will have a native dependency or a WebAssembly decoder, which undoes much of the reason to pick this one. The second is the partial coverage. The maintainer is explicit that the Photoshop implementation is a draft and MakerNote coverage is partial, that MPF is not read for JPEG XL, that the ICC profile inside a JPEG XL codestream is not read, and that IPTC for the newer formats comes from Exif carriers rather than a native block. A project that needs a specific tag from a specific format should verify that combination against the table and the footnotes before committing, and the project asks you to file an issue with an attached example image if something is missing. The third is the trust issue with untrusted files, and here the recent release history is relevant: v4.48.1 is described as using less memory and time on crafted files, with tag and type fixes, and v4.49.0 includes description and security fixes. A parser that runs on files uploaded by strangers is a parser that has to be kept current, and a project that pins an old version of this library is pinning a known set of parser bugs. The fourth is that the library is not a validator: it reads what the file claims, so metadata is self-reported data and should be treated as untrusted input by anything downstream that acts on it, such as a GPS coordinate written straight into a database.

Editorial conclusion

Adopt ExifReader if you need to read photo metadata in a browser or in Node without a native module, you want the full metadata set rather than a few tags, and you care about bundle size. Do not adopt it for image processing beyond metadata, since it parses headers and tags and does not decode pixels, and do not rely on it for a format or tag it has not been tested against, since several entries in the support table are partial by the maintainer's own account. Before you upgrade, read the changelog entries for the version you are moving to, and note that the current release is v4.50.0 from 2026-10-12, with the previous two releases adding HEIC and AVIF image details and reducing memory use on crafted files.

Frequently asked questions

What does ExifReader parse?

It parses image files and extracts metadata, and it can also extract an embedded thumbnail. It supports JPEG, JPEG XL, TIFF, PNG, HEIC, AVIF, WebP and GIF files, with Exif, IPTC, XMP, ICC and MPF metadata depending on the file type.

How do I install ExifReader?

Through npm with `npm install exifreader --save`, or Bower with `bower install exifreader --save`. You can also clone the git repository and run npm install in it, after which the transpiled, concatenated and minified ES5 file is in the dist folder with a sourcemap file.

How do I read a tag in ExifReader?

Call ExifReader.load with the file and await it, then read the tag from the returned object. Each tag has a description field with the human-readable value and a value field with the raw value, so `tags['DateTimeOriginal'].description` gives a formatted date and `tags['DateTimeOriginal'].value` the raw one.

Is ExifReader usable in a browser?

Yes. It can be used in a browser or from Node, and it supports the ESM, AMD, CommonJS and globals module formats, so it works from Webpack, RequireJS, Browserify and Node. The package also ships a command line entry named exifreader.

What licence is ExifReader released under?

The MPL-2.0 licence, with the LICENSE file in the repository root. The current release is v4.50.0 from 2026-10-12, following v4.49.0 on 2026-10-11 and v4.48.1 on 2026-10-10, and the last push to the repository was on 2026-10-16.

Official sources

  1. Issues
  2. License: MPL-2.0
  3. mattiasw/ExifReader on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mattiasw-exifreader.svg)](https://hysenlabs.com/projects/mattiasw-exifreader)

Was this useful?