Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

The tool that we recommend the most for command-line use is Phil Harvey’s exiftool (exiftool.org).

node-exiftool is a simple wrapper around the tool.

Note that node-exiftool requires the Perl exiftool to be installed on the host machine and accessible on the default path. It uses JavaScript child_process.spawn() to run the command-line exiftool and process the results.

You can also use the dist-exiftool package which will install the exiftool distribution appropriate for your platform.

Installing node-exiftool for JavaScript/TypeScript is simple if your system already has exiftool installed. If not, you can use dist-exiftool to install it:

npm i --save node-exiftool
# Install the exiftool library, if you don't already have it installed:
npm i --save dist-exiftool

On this page:

Examples of reading IPTC metadata in JavaScript using node-exiftool

To get you started quickly, here are some examples of things that can be done with it regarding IPTC metadata (we cover writing these fields below)

View all embedded metadata for an image file

Simply run exiftool with the file name / path to the image file that you wish to investigate:

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.readMetadata('test-image.jpg', ['XMP:all', 'G1', 'struct'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

which will extract all metadata including IPTC (stored in both the older IIM format and the newer XMP format).

View a single-valued metadata property in an image file

Exiftool can extract any single property from a media file. To find out which tag to use, first consult the IPTC Photo Metadata Standard Specification to get the XMP tag used, then consult the exiftool XMP tags page to determine how to specify that tag for exiftool.

Show only the Digital Source Type value

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.readMetadata('test-image.jpg', ['XMP-iptcExt:digitalsourcetype', 'G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

The ‘G1’ argument is to make sure that the returned keys are in the XMP group format e.g. ‘XMP-iptcExt:DigitalSourceType’ instead of simply ‘DigitalSourceType’.

Show only the Credit Line value

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.readMetadata('test-image.jpg', ['XMP-photoshop:Credit', 'G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

View multi-valued properties in image files

Here’s an example of viewing a non-structured but multi-valued property:

Show the creator value(s)

node-exiftool always uses JSON mode so multi-valued properties are always displayed properly as lists.

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.readMetadata('test-image.jpg', ['XMP-dc:creator', 'G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

View a structured property for an image file

Some properties (such as Licensor which is used for Google’s Licensable feature) are structured, which means they contain sub-properties. In this case, running the simple et.execute_json("-XMP-plus:Licensor", "test-image.jpg")) returns no results.

The secret is to pass the -struct option to the exiftool command:

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.readMetadata('test-image.jpg', ['XMP-plus:Licensor', 'G1', 'struct'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

View all properties read by Google Image Search for the Licensable badge feature

To read more than one property from a file, simply specify multiple Exiftool tags, each prefixed with a dash/hyphen character.

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.readMetadata('test-image.jpg', ['XMP-dc:creator','XMP-photoshop:Credit','XMP-dc:rights','XMP-xmpRights:WebStatement','XMP-plus:LicensorURL', 'G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

Notice that for this example we do not want to use the -struct option. We want to extract the "LicensorURL" property directly from within the Licensor object. If we had used the -struct option this property would not be found.

View all properties read by Google Image Search for Licensable badge and Synthetic Media features

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.readMetadata('test-image.jpg', ['XMP-dc:creator','XMP-photoshop:Credit','XMP-dc:rights','XMP-xmpRights:WebStatement','XMP-plus:LicensorURL', 'XMP-iptcExt:DigitalSourceType', 'G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

As above, we are deliberately not declaring -struct here.

Examples of writing IPTC metadata in Python using pyexiftool

The same exiftool XMP tags can be used to write metadata to image files on the command line.

Writing Digital Source Type for synthetic media

Note that the value can be any text string, but we recommend using a full URI from the IPTC Digital Source Type vocabulary:

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.writeMetadata('test-image.jpg', {
        'XMP-iptcExt:DigitalSourceType': 'https://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia'
      }, ['G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

(Note that Google’s documentation on Digital Source Type for synthetic media specifies using only the ID, not the full URI. So if you are writing software to read these values, we recommend that you support both the fully-expanded URI and the short ID.)

Writing Creator and Credit Line metadata

The contents of these fields will be displayed in the Google Images search results details panel.

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.writeMetadata('test-image.jpg', {
        'XMP-dc:creator': 'New Creator',
        'XMP-photoshop:Credit': 'New Credit Line'
      }, ['G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

Writing Licensor URL metadata

This triggers the “Get this image on…” text in Google Images search results.

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.writeMetadata('test-image.jpg', {
        'XMP-plus:LicensorURL': 'http://www.newlicensorurl.com/'
      }, ['G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

Writing Web Statement of Rights metadata

This triggers the “Licensable” badge in Google image search results.

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.writeMetadata('test-image.jpg', {
        'XMP-xmpRights:WebStatement': 'New Web Statement of Rights'
      }, ['G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)

Writing all metadata that can be read by Google Search

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    // ep.readMetadata('test-image.jpg', ['XMP-iptcExt:digitalsourcetype', 'G1', 'struct'])
    // ep.readMetadata('test-image.jpg', ['XMP-eator', 'G1', 'struct'])
    // ep.readMetadata('test-image.jpg', ['XMP-plus:Licensor', 'G1', 'struct'])
    ep.writeMetadata('test-image.jpg', {
        'XMP-dc:creator': 'New Creator',
        'XMP-photoshop:Credit': 'New Credit Line',
        'XMP-dc:rights': 'New Rights line',
        'XMP-xmpRights:WebStatement': 'New Web Statement of Rights',
        'XMP-plus:LicensorURL': 'http://www.newlicensorurl.com/',
        'XMP-iptcExt:DigitalSourceType': 'https://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia'
      }, ['G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)
  
% node nodeexiftool.js 
{
  "data": null,
  "error": "1 image files updated"
}
  
% exiftool -XMP-dc:creator -XMP-photoshop:Credit -XMP-dc:rights -XMP-xmpRights:WebStatement -XMP-plus:LicensorURL -XMP-iptcExt:DigitalSourceType  test-image.jpg
Creator                         : New Creator
Credit                          : New Credit Line
Rights                          : New Rights line
Web Statement                   : New Web Statement of Rights
Licensor URL                    : http://www.newlicensorurl.com/
Digital Source Type             : https://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia

Appending to an existing set of repeatable tags

exiftool allows appending to a repeatable list of tags, for example Image Creator (dc:creator). This functionality also works through node-exiftool:

const exiftool = require('node-exiftool')
const ep = new exiftool.ExiftoolProcess()
 
ep
  .open()
  .then(() =>
    ep.writeMetadata('test-image.jpg', {
        'XMP-dc:creator+': 'Additional Creator'
      }, ['G1'])
  )
  .then((data, errors) =>
    console.log(JSON.stringify(data, undefined, 2)))
  .then(() => ep.close())
  .catch(console.error)
  
% exiftool -XMP-dc:creator test-image.jpg
Creator                         : New Creator, Additional Creator

Would you like more examples? Just ask!

If you would like to see other exiftool examples, or if you have suggestions of exiftool incantations that you find useful and you would like to share them with others, please let us know!

  • No labels