{"id":22508104,"url":"https://github.com/mattduffy/exiftool","last_synced_at":"2025-08-03T13:30:46.052Z","repository":{"id":63643296,"uuid":"551756836","full_name":"mattduffy/exiftool","owner":"mattduffy","description":"A Node.js package wrapping the incredible exiftool (created by Phil Harvey).","archived":false,"fork":false,"pushed_at":"2024-09-24T04:52:32.000Z","size":11846,"stargazers_count":9,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-06T03:17:35.370Z","etag":null,"topics":["exiftool","image-metadata","metadata","nodejs","npm","npm-package"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mattduffy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-15T03:07:33.000Z","updated_at":"2024-09-24T04:52:35.000Z","dependencies_parsed_at":"2024-01-01T05:27:39.542Z","dependency_job_id":"319cce49-69f3-4bc0-af32-d1acbe75a275","html_url":"https://github.com/mattduffy/exiftool","commit_stats":{"total_commits":74,"total_committers":1,"mean_commits":74.0,"dds":0.0,"last_synced_commit":"275aabe75913aa967d1e9c4316b6c32adbb11ae4"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattduffy%2Fexiftool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattduffy%2Fexiftool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattduffy%2Fexiftool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattduffy%2Fexiftool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mattduffy","download_url":"https://codeload.github.com/mattduffy/exiftool/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228410889,"owners_count":17915544,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["exiftool","image-metadata","metadata","nodejs","npm","npm-package"],"created_at":"2024-12-07T01:18:15.657Z","updated_at":"2024-12-07T01:18:16.359Z","avatar_url":"https://github.com/mattduffy.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Extract Image Metadata with Exiftool\n\nThis package for Node.js provides an object-oriented wrapper around the phenomenal utility, [exiftool](https://exiftool.org), created by [Phil Harvey](https://exiftool.org/index.html#donate).  This package requires the ```exiftool``` perl library to already be installed.  Installation instructions can be found [here](https://exiftool.org/install.html).  This package is compatible with POSIX systems; it will not work on a Windows machine.  This package will not run in a browser.\n\n## Using Exiftool\nThis package attempts to abstract the various uses of exiftool into a small collection of distinct methods that help to reduce the difficulty of composing complex metadata processing incantations.  The Exiftool class instantiates with a reasonable set of default options to produce explicitly labeled, yet compact, metadata output in JSON format.  The included options are easily modified if necessary, and even more customized exiftool incantations can be created and saved as [shortcuts](https://exiftool.org/TagNames/Shortcuts.html) in an [exiftool.config](https://exiftool.org/config.html) file.  \n\n```bash\nnpm install --save @mattduffy/exiftool\n```\n\n```javascript\nimport { Exiftool } from '@mattduffy/exiftool'\nlet exiftool = new Exiftool()\n```\n\nThe Exiftool class constructor does most of the initial setup.  A call to the ```init()``` method is currently necessary to complete setup because it makes some asynchronous calls to determine the location of exiftool, whether the exiftool.config file is present - creating one if not, and composing the exiftool command string from the default options.  The ```init()``` method takes a string parameter which is the file system path to an image file or a directory of images.  This is an **Async/Await** method.\n```javascript\nexiftool = await exiftool.init( '/www/site/images/myNicePhoto.jpg' )\n\n// or in one line...\nlet exiftool = await new Exiftool().init( '/www/site/images/myNicePhoto.jpg' )\n```\nIt is also possible to pass an array of strings to the ```init()``` method if you have more than one image.\n```javascript\nlet images = ['/www/site/images/one.jpg', '/www/site/images/two.jpg', '/www/site/images/three.jpg']\nlet exiftool = await new Exiftool().init(images)\n```\n\nAt this point, Exiftool is ready to extract metadata from the image ```myNicePhoto.jpg```.  Use the ```getMetadata()``` to extract the metadata.    This is an **Async/Await** method.  \n\nThere are a few options to choose what metadata is extracted from the file:\n- using default options, including a pre-configured shortcut\n- override the default shortcut name with a different one (already added to the exiftool.config file)\n- adding additional [Exiftool Tags](https://exiftool.org/TagNames/index.html) to extract beyond those included in the default shortcut\n\n```javascript\n// Using just the default options.\nlet metadata1 = await exiftool.getMetadata()\n\n// Changing the image path, if you want, for some reason.\nlet metadata2 = await exiftool.getMetadata( '/path/to/a/different/image.jpg', '', '' )\n\n// Using all the default options, but calling a different shortcut \n// previously saved to the exiftool.config file.\nlet metadata3 = await exiftool.getMetadata( '', 'ADifferentSavedShortcut', '' )\n\n// Adding Tags to command to be extracted, in additon to those \n// specified in the shortcut.  For example, extracting LensInfo, \n// FocalLength, ImageWidth and ImageHeight values (if present).\nlet metadata4 = await exiftool.getMetadata( '', '', 'EXIF:LensInfo', 'EXIF:FocalLength', 'File:ImageWidth', 'File:ImageHeight' )\n\n// All three parameters can be used at once if desired.\nlet metadata5 = await exiftool.getMetadata( '/path/to/a/different/image.jpg', 'ADifferentSavedShortcut', 'EXIF:LensInfo', 'EXIF:FocalLength', 'File:ImageWidth', 'File:ImageHeight' )\n```\n\nThe simplest use of Exiftool looks like this:\n ```javascript\nimport { Exiftool } from '@mattduffy/exiftool'\nlet exiftool = await new Exiftool().init( 'images/copper.jpg' )\nlet metadata = await exiftool.getMetadata()\nconsole.log( metatdata )\n// [\n//   {\n//     SourceFile: 'images/copper.jpg',\n//     'File:FileName': 'copper.jpg',\n//     'EXIF:ImageDescription': 'Copper curtain fixture',\n//     'IPTC:ObjectName': 'Tiny copper curtain rod',\n//     'IPTC:Caption-Abstract': 'Copper curtain fixture',\n//     'IPTC:Keywords': 'copper curtain fixture',\n//     'Composite:GPSPosition': `48 deg 8' 49.20\" N, 17 deg 5' 52.80\" E`\n//   },\n//   {\n//     exiftool_command: '/usr/local/bin/exiftool -config /home/node_packages/exiftool/exiftool.config -json -BasicShortcut -groupNames -s3 -quiet --ext TXT --ext JS --ext JSON --ext MJS --ext CJS --ext MD --ext HTML images/copper.jpg'\n//   },\n//   1\n// ]\n ```\nThe ```exiftool_command``` property is the command composed from all the default options, using the pre-configured BasicShortcut saved in the exiftool.config file.\n\nThe last element in the metadata array is the count of files that exiftool inspected and returned data for.\n\n#### Command Not Found!\n\nThis node.js package can only function if [exiftool](https://exiftool.org/install.html) is installed.  This node.js package DOES NOT install the necessary, underlying ```exiftool``` executable.  If ```exiftool``` is not installed, or is not available in the system path, it will throw an error and interrupt execution.\n\n```javascript\nlet exiftool = await new Exiftool().init( 'images/copper.jpg' )\nError: ATTENTION!!! exiftool IS NOT INSTALLED.  You can get exiftool here: https://exiftool.org/install.html\n    at Exiftool.init (file:///www/exiftool/src/index.js:83:13)\n    at async REPL17:1:38 {\n  [cause]: Error: Exiftool not found?\n      at Exiftool.which (file:///www/exiftool/src/index.js:498:13)\n      at async Exiftool.init (file:///www/exiftool/src/index.js:73:28)\n      at async REPL17:1:38\n      at async node:repl:646:29 {\n    [cause]: Error: Command failed: which exitfool\n```\n\n#### Extracting Binary Tag Data\nThere are several tags that store binary data, such as image thumbnails, color profile, image digests, etc..  The default state for exiftool is to not extract binary data from tags.  If you would like to extract the binary data, use the ```enableBinaryTagOutput(\u003cboolean\u003e)``` method before calling the ```getMetadata()``` method.\n\n```javascript\nlet exiftool = await new Exiftool().init( 'images/copper.jpg' )\nexiftool.enableBinaryTagOutput(true)\nlet metadata = await exiftool.getMetadata()\nlet thumbnail = metadata[0]['EXIF:ThumbnailImage']\nconsole.log(thumbnail)\n// 'base64:/9j/4AAQSkZJRgABAgEASABIAAD/4QKkaHR.........'\n```\n\n#### Embedded Thumbnail Images\nThere are several tags that may store tiny thumbnails or previews of the containing image file.  ```Exiftool``` provides two simple methods for accessing thumbnail data.  The ```getThumbnails()``` method will return a JSON object containing each version of thumbnail data (Base64 encoded) embedded in the file.  This method is an **Async/Await** method.\n```javascript\nlet exiftool = await new Exiftool().init( 'images/copper.jgp' )\nconst thumbnails = await exiftool.getThumbnails()\nconsole.log(thumbnails)\n// [\n//   {\n//     SourceFile: '/www/images/copper.jpg',\n//     'EXIF:ThumbnailImage': 'base64:/9j/wAA...'\n//   },\n//   {\n//     exiftool_command: '/usr/local/bin/exiftool -config \"/../exiftool/src/exiftool.config\" -json -Preview:all  -groupNames -s3 -quiet --ext cjs --ext css --ext html --ext js --ext json --ext md --ext mjs --ext txt -binary \"/www/images/copper.jpg\"'\n//   },\n//   { format: 'json' },\n// ]\n```\n\nSetting a thumbnail is easy, with the ```setThumbnail(\u003cthumbnail-path\u003e)``` method.  The first parameter is required, a path to the thumbnail file to be embedded.  The default tag name used to store the thumbnail data is ```EXIF:ThumbnailImage```.  This is an **Async/Await** method.\n```javascript\nlet exiftool = await new Exiftool().init( 'images/copper.jgp' )\nconst result = await exiftool.setThumbnails('images/new-thumbnail.jpg')\nconsole.log(result)\n// {\n//   stdout: '',\n//   stderr: '',\n//   exiftool_command: '/usr/local/bin/exiftool -config \"/../exiftool/src/exiftool.config\" -json \"-EXIF:ThumbnailImage\u003c=/www/images/new-thumbnail.jpg\" \"/www/images/copper.jpg\"',\n//   success: true\n// }\n```\n\n#### Metadata Output Format\nThe default output format when issuing metadata queries is JSON.  You can change the output format to XML by calling the ```setOutputFormat(\u003cxml|json\u003e)``` method before calling the ```getMetadata()``` method.\n\n```javascript\nlet exiftool = await new Exiftool().init( 'images/copper.jpg' )\nexiftool.setOutputFormat('xml')\nlet xml = await exiftool.getMetadata()\nconsole.log(xml)\n// [\n//  \"\u003c?xml version='1.0' encoding='UTF-8'?\u003e\n//  \u003crdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'\u003e\n//    \u003crdf:Description rdf:about='__tests__/images/copper.jpg'\n//      xmlns:et='http://ns.exiftool.org/1.0/' et:toolkit='Image::ExifTool 12.68'\n//      xmlns:System='http://ns.exiftool.org/File/System/1.0/'\n//      xmlns:File='http://ns.exiftool.org/File/1.0/'\u003e\n//     \u003cSystem:FileSize\u003e3.3 MB\u003c/System:FileSize\u003e\n//     \u003cFile:FileType\u003eJPEG\u003c/File:FileType\u003e\n//     ...\n//     \u003cFile:YCbCrSubSampling\u003eYCbCr4:2:0 (2 2)\u003c/File:YCbCrSubSampling\u003e\n//    \u003c/rdf:Description\u003e\n//  \u003c/rdf:RDF\u003e\",\n//  { raw: \"\u003c?xml version='1.0' encoding='UTF-8'?\u003e...\" },\n//  { format: 'xml' },\n//  { exiftool_command: '/usr/local/bin/exiftool -config exiftool.config -json -xmp:all  -groupNames -s3 -quiet --ext cjs --ext css --ext html --ext js --ext json --ext md --ext mjs --ext txt images/copper.jpg'},\n//  1,\n// ]\n```\n\n#### Location Coordinate Output Formatting\nThe default output format used by ```exiftool``` to report location coordinates looks like ```54 deg 59' 22.80\"```.  The coordinates output format can be changed using `printf` style syntax strings. To change the location coordinate output format, use the ```setGPSCoordinatesOutputFormat(\u003cprintf fmt|'[+]gps'\u003e)``` method before calling the ```getMetadata()``` method.  ```ExifTool``` provides a simple alias ```gps``` to set the output to typical GPS style ddd.nnnnnn notation (%.6f printf syntax, larger number will provide higer precision).  See the [exiftool -coordFormat](https://exiftool.org/exiftool_pod.html#c-FMT--coordFormat) documentation for more details on controlling coordinate output formats.\n\n```javascript\nlet exiftool = await new Exiftool().init( 'images/copper.jpg' )\nlet defaultLocationFormat = await exiftool.getMetadata('', null, 'EXIF:GPSLongitude', 'EXIF:GPSLongitudeRef')\nconsole.log(defaultLocationFormat[0]['EXIF:GPSLongitude'], defaultLocationFormat[0]['EXIF:GPSLongitudeRef'])\n// 122 deg 15' 16.51\" West\nexiftool.setGPSCoordinatesOutputFormat('gps')\n// or exiftool.setGPSCoordinatesOutputFormat('+gps') for signed lat/lon values in Composite:GPS* tags\nlet myLocationFormat = await exiftool.getMetadata('', null, 'EXIF:GPSLongitude', 'EXIF:GPSLongitudeRef')\nconsole.log(myLocationFormat[0]['EXIF:GPSLongitude'], myLocationFormat[0]['EXIF:GPSLongitudeRef'])\n// 122.254586 West\n```\n\n#### Raw XMP Packet Data\nTo extract the full Adobe XMP packet, if it exists within an image file, you can use the ```getXmpPacket()``` method.  This method will extract only the xmp metadata.  The metadata will be a serialized string version of the raw XMP:RDF packet object.  This is an **Async/Await** method. \n\n```javascript\nlet exiftool = await new Exiftool().init( 'images/copper.jpg' )\nlet xmpPacket = await exiftool.getXmpPacket()\nconsole.log(xmpPacket)\n// {\n//    exiftool_command: '/usr/local/bin/exiftool -config /app/src/exiftool.config -xmp -b /www/images/copper.jpg',\n//    xmp: '\u003c?xpacket?\u003e\u003c?xpacket?\u003e\u003cx:xmpmeta\u003e\u003crdf:RDF\u003e\u003crdf:Description\u003e\u003cxmpMM:...\n//    ...\n//    \u003c/rdf:Description\u003e\u003c/rdf:RDF\u003e\u003c/x:xmpmeta\u003e'\n// }\n```\n\n#### XMP Structured Tags\nXMP tags can contain complex, structured content.  ```exiftool``` is able to extract this [structured content](https://exiftool.org/struct.html), or flatten it into a single value.  The default state for exiftool is to flatten the tag values.  If you would like to extract the complex structured data, use the ```enableXMPStructTagOutput(\u003cboolean\u003e)``` method before calling the ```getMetadata()``` method.  See the [exiftool -struct](https://exiftool.org/exiftool_pod.html#struct---struct) documentation for more details on how to access nested / structured fields in XMP tags.\n\n```javascript\nlet exiftool = await new Exiftool().init( 'images/copper.jpg' )\nexiftool.enableXMPStructTagOutput(true)\nlet metadata = await exiftool.getMetadata()\n```\n\n#### MWG Composite Tags\nThe Metadata Working Group has created a recommendation for how to read and write to tags which contain values repeated in more than one tag group.  ```exiftool``` provides the ability to keep these overlapping tag values synchronized with the [MWG module](https://exiftool.org/TagNames/MWG.html).  Use the ```useMWG(\u003cboolean\u003e)``` method to cause ```exiftool``` to follow the MWG 2.0 recommendations.  The overlapping tags will be reduced to their 2.0 recommendation and reported assigned to the ```Composite:*``` tag group.\n\n```javascript\nlet exiftool = await new Exiftool().init( 'images/IPTC-PhotometadataRef-Std2021.1.jpg' )\nexiftool.useMWG(true)\nlet metadata = await exiftool.getMetadata('', '', '-MWG:*')\nconsole.log(metadata[0])\n// [\n//   {\n//     SourceFile: 'images/IPTC-PhotometadataRef-Std2021.1.jpg',\n//     'Composite:City': 'City (Location shown1) (ref2021.1)',\n//     'Composite:Country': 'CountryName (Location shown1) (ref2021.1)',\n//     'Composite:Copyright': 'Copyright (Notice) 2021.1 IPTC - www.iptc.org  (ref2021.1)',\n//     'Composite:Description': 'The description aka caption (ref2021.1)',\n//     'Composite:Keywords': [ 'Keyword1ref2021.1', 'Keyword2ref2021.1', 'Keyword3ref2021.1' ]\n//   },\n//   {\n//     exiftool_command: '/usr/local/bin/exiftool -config /home/node_packages/exiftool/exiftool.config -json -BasicShortcut -groupNames -s3 -quiet --ext TXT --ext JS --ext JSON --ext MJS --ext CJS --ext MD --ext HTML images/IPTC-PhotometadataRef-Std2021.1.jpg'\n//   },\n//   1\n// ]\n```\n\n#### Excluding Files by File Type\nBecause ```exiftool``` is such a well designed utility, it naturally handles metadata queries to directories containing images just as easily as to a specific image file.  It will automatically recurse through a directory and process any image file types that it knows about.  Exiftool is designed with this in mind, by setting a default list of file types to exclude, including TXT, JS, CJS, MJS, JSON, MD, HTML, and CSS.  This behavior can be altered by modifying the list of extensions to exclude with the ```setExtensionsToExclude()``` method.\n\n```javascript\nimport { Exiftool } from '@mattduffy/exiftool'\nlet exiftool = new Exiftool()\nlet extensionsArray = img.getExtensionsToExclude()\nextensionsArray.push( 'ESLINT' )\nimg.setExtensionsToExclude( extensionsArray )\nexiftool = await exiftool.init( 'images/' )\nlet metadata = await exiftool.getMetadata()\n console.log( metatdata )\n[\n  {\n    SourceFile: 'images/IMG_1820.heic',\n    'File:FileName': 'IMG_1820.heic',\n    'Composite:GPSPosition': `48 deg 8' 49.20\" N, 17 deg 5' 52.80\" E`\n  },\n  {\n    SourceFile: 'images/copper.jpg',\n    'File:FileName': 'copper.jpg',\n    'EXIF:ImageDescription': 'Copper curtain fixture',\n    'IPTC:ObjectName': 'Tiny copper curtain rod',\n    'IPTC:Caption-Abstract': 'Copper curtain fixture',\n    'IPTC:Keywords': 'copper curtain fixture',\n    'Composite:GPSPosition': `48 deg 8' 49.20\" N, 17 deg 5' 52.80\" E`\n  },\n  {\n    SourceFile: 'images/IMG_1820.jpg',\n    'File:FileName': 'IMG_1820.jpg',\n    'Composite:GPSPosition': `48 deg 8' 49.20\" N, 17 deg 5' 52.80\" E`\n\n  },\n  {\n    exiftool_command: '/usr/local/bin/exiftool -config /home/node_package_development/exiftool/exiftool.config -json -coordFormat \"%.6f\"  -BasicShortcut -groupNames -s3 -quiet --ext TXT --ext JS --ext JSON --ext MJS --ext CJS --ext MD --ext HTML --ext ESLINT images/'\n  },\n  3\n]\n```\n\n### The exiftool.config File\nThis file is not required to be present to process metadata by the original ```exiftool```, but it can help a lot with complex queries, so this Exiftool package uses it.  During the ```init()``` setup, a check is performed to see if the file is present in the root of the package directory.  If no file is found, a very basic file is created, populated with a simple shortcut called ```BasicShortcut```.  The path to this file can be overridden to use a different file.\n\n```javascript\nlet exiftool = await new Exiftool().init( '/path/to/image.jpg' )\nlet oldConfigPath = exiftool.getConfigPath()\nconsole.log( oldConfigPath )\n{\n  value: '/path/to/the/exiftool/exiftool.config',\n  error: null\n}\n```\n```javascript\nlet newConfigFile = '/path/to/new/exiftool.config'\nlet result = await exiftool.setConfigPath( newConfigFile )\nlet metadata = await exiftool.getMetadata()\n```\n\n### Shortcuts\nThe original ```exiftool``` provides a very convenient way to save arbitrarily complex metadata queries in the form of **shortcuts** saved in an ```exiftool.config``` file.  New shortcuts can be added to the ```exiftool.config``` managed by the package.  If a different ```exiftool.config``` file is used, do not try to save new shortcuts to that file with this method.  To add a new shortcut, use ```addShortcut()```.  This is an **Async/Await** method.\n\n```javascript\nlet exiftool = await new Exiftool().init( '/path/to/image.jpg' )\n// Check to see if a shortcut with this name is already \n// present in the package provided exiftool.config file\nif (!await exiftool.hasShortcut( 'MyCoolShortcut' )) {\n  // Shortcut was not found, save the shortcut definition to the exiftool.config file\n  let result = await exiftool.addShortcut( \"MyCoolShortcut =\u003e ['EXIF:LensInfo', 'EXIF:FocalLength', 'File:ImageWidth', 'File:ImageHeight']\" )\n  console.log( result )\n}\n```\nTo change the default shortcut (BasicShortcut) to something else, that has already been added to the ```exiftool.config``` file, use the ```setShortcut()``` method.\n\n```javascript\nlet exiftool = await new Exiftool().init( '/path/to/image.jpg' )\nlet result = exiftool.setShortcut( 'MyCoolShortcut' )\nlet metadata = await exiftool.getMetadata()\n\n// Alternatively, pass the shortcut name as a parameter in the getMetadata() method\nlet metadata = await exiftool.getMetadata( '', 'MyCoolShortcut', '' )\n```\n\nTo remove a shortcut from the package provided ```exiftool.config``` file use the ```removeShortcut()``` method.  This is an **Async/Await** method.\n\n```javascript\nlet exiftool = await new Exiftool().init( '/path/to/image.jpg' )\n// Check to see if a shortcut with this name is already \n// present in the package provided exiftool.config file\nif (await exiftool.hasShortcut( 'MyCoolShortcut' )) {\n  // Shortcut was found, now remove it\n  let result = await exiftool.removeShortcut( 'MyCoolShortcut' )\n  console.log( result )\n}\n```\nThe ```exiftool.config``` file generated by ```Exiftool``` includes a few useful shortcuts:\n- BasicShortcut\n- Location\n- StripGPS\n\n\nExiftool creates a backup of the ```exiftool.config``` file each time it is modified by the ```addShortcut()``` or ```removeShortcut()``` methods.\n\n### Writing Metadata to a Tag\n```exiftool``` makes it easy to write new metadata values to any of the hundreds of tags it supports by specifying the tag name and the new value to write.  Any number of tags can be written to in one command.  A full discussion is beyond the scope of this documentation, but information on the types of tag values (strings, lists, numbers, binary data, etc.) can be found [here](https://exiftool.org/TagNames/index.html).  Exiftool provides the ```writeMetadataToTag()``` method to support this functionality.  This method works on a single image file at a time.  It takes either a string, or an array of strings, formated according to these [rules](https://exiftool.org/exiftool_pod.html#WRITING-EXAMPLES).\n\nThe general format to write a new value to a tag is: ```-TAG=VALUE``` where TAG is the tag name, ```=``` means write the new ```VALUE```.  For tags that store list values, you can add an item to the list ```-TAG+=VALUE```.  The ```+=``` is like ```Array.push()```.  Likewise, ```-TAG-=VALUE``` is like ```Array.pop()```.\n\nThis is an **Async/Await** method.\n\n```javascript\nlet exiftool = await new Exiftool().init( '/path/to/image.jpg' )\nlet tagToWrite = '-IPTC:Headline=\"Wow, Great Photo!\"'\nlet result1 = await exiftool.writeMetadataToTag( tagToWrite )\nconsole.log(result1)\n//{\n//   value: true,\n//   error: null,\n//   command: '/usr/local/bin/exiftool -IPTC:Headline=\"Wow, Great Photo!\" /path/to/image.jpg',\n//   stdout: '1 image files updated'\n//}\n```\nMultiple tags can be written to at once by passing an array to ```writeMetadataToTag()```.  \n\n```javascript\nlet exiftool = await new Exiftool().init( '/path/to/image.jpg' )\nlet tagArray = ['-IPTC:Contact=\"Photo McCameraguy\"', '-IPTC:Keywords+=News', '-IPTC:Keywords+=Action']\nlet result2 = await exiftool.writeMetadataToTag( tagArray )\nconsole.log(result2)\n//{\n//   value: true,\n//   error: null,\n//   command: '/usr/local/bin/exiftool -IPTC:Contact=\"Photo McCameraguy\" -IPTC:Keywords+=News -IPTC:Keywords+=Action /path/to/image.jpg',\n//   stdout: '1 image files updated'\n//}\n```\n\n#### Setting a Location\nThere are many tags that can contain location-related metadata, from GPS coordinates, to locality names.  Setting a location is complicated by the fact that there is more than one tag group capable of holding these valuse.  IPTC, EXIF, and XMP can all store some amount of overlapping location data.  The Metadata Working Group provides a way to keep some of these values in sync across tag groups, but doesn't include location coordinates.  To help keep location data accurate and in-sync, ```Exiftool``` provides the ```setLocation()``` method.  It takes an object literal parameter with latitude/longitude coordinates and locality names if desired.  This is an **Async/Await** method.\n\n```javascript\nlet exiftool = await new Exiftool().init('/path/to/image.jpg')\nconst coordinates = {\n  latitude: 40.748193,\n  longitude: -73.985062,\n  city: 'New York City',              // optional\n  state: 'New York',                  // optional\n  country: 'United States',           // optional\n  countryCode: 'USA',                 // optional\n  location: 'Empire State Building',  // optional\n}\nconst result = await exiftool.setLocation(coordinates)\n```\n\n### Clearing Metadata From a Tag\nTags can be cleared of their metadata value.  This is essentially the same as writing an empty string to the tag.  This is slighlty different that stripping the tag entirely from the image.  Exiftool provides the ```clearMetadataFromTag()``` method to clear tag values.  This leaves the empty tag in the image file so it can be written to again if necessary.  Like the ```writeMetadataToTag()``` method, this one also takes either a string or an array of strings as a parameter.  This is an **Async/Await** method.\n\n```javascript\nlet exiftool = await new Exiftool().init('/path/to/image.jpg')\nlet tagToClear = '-IPTC:Contact^='\nlet result = await exiftool.clearMetadataFromTag(tagToClear)\nconsole.log(result)\n```\n\n### Stripping Metadata From an Image\nIt is possible to strip all of the existing metadata from an image with this Exiftool package.  The default behavior of the original ```exiftool``` utility, when writing metadata to an image is to make a backup copy of the original image file.  The new file will keep the original file name, while the backup will have **_original** appended to the name.  Exiftool maintains this default behavior.\n\n```javascript\nlet exiftool = await new Exiftool().init( '/path/to/image.jpg' )\nlet result = await exiftool.stripMetadata()\n/*\n  This will result in two files:\n  - /path/to/image.jpg (contains no metadata in the file)\n  - /path/to/image.jpg_original (contains all the original metadata)\n*/\n```\n\nIf you would like to change the default exiftool behavior, to overwrite the original image file, call the ```setOverwriteOriginal(\u003cboolean\u003e)``` method after the ```init()``` method.\n\n```javascript\nlet exiftool = await new Exiftool().init('myPhoto.jpg')\nexiftool.setOverwriteOriginal(true)\nlet result await exiftool.stripMetadata()\n/*\n  This will result in one file:\n  - /path/to/myPhoto.jpg (contains no metadata in the file)\n*/\n```\n\nIf GPS location data is the only metadata that needs to be stripped, the ```stripLocation()``` method can be used.  This method updates the images in place.  It can be called on either a directory of images or a single image.  This is an **Async/Await** method.\n```javascript\nlet exiftool = await new Exiftool().init('/path/to/images')\nawait exiftool.stripLocation()\n// {\n//   stdout: '    1 directories scanned\\n    4 image files updated\\n',\n//   stderr: '',\n//   exiftool_command: '/usr/local/bin/exiftool -gps:all= /path/to/images/'\n// }\n```\n\n### Making Metadata Queries Directly\nIt may be more convenient sometimes to issue a metadata query to ```exiftool``` directly rather than compose it through the class configured default options and methods.  Running complex, one-off queries recursively across a directory of images might be a good use for issuing a command composed outside of Exiftool.  This is an **Async/Await** method.\n\n```javascript\nlet exiftool = new Exiftool()\nlet result = await exiftool.raw('/usr/local/bin/exiftool b -jpgfromraw -w %d%f_%ue.jpg -execute -binary -previewimage -w %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg -common_args --ext jpg /path/to/image/directory')\nconsole.log(result)\n```\n\n### Setting File Extension for Exiftool to ignnore\nExiftool maintains a list of file extensions to tell ```exiftool``` to ignore when the target of the metadata query is a directory rather than a file.  This list of file extensions can be updated as necessary.  The ```setExtensionsToExclude()``` method may take two array parameters.  The first paramater is an array of file extensions to add to the exclude list.  The second paramater is an array of file extensions to remove from the current exclude list.\n\n```javascript\nlet exiftool = new Exiftool()\nconsole.log(exiftool.getExtensionsToExclude())\n// [ 'cjs', 'css', 'html', 'js', 'json', 'md', 'mjs', 'txt' ]\nconst extensionsToAdd = ['scss','yaml']\nconst extensionsToRemove = ['txt']\nexiftool.setExtensionsToExclude(extensionsToAdd, extensionsToRemove)\nconsole.log(exiftool.getExtensionsToExclude())\n// [ 'cjs', 'css', 'html', 'js', 'json', 'md', 'mjs', 'scss', 'yaml' ]\n```\n```javascript\n// Just adding file extensions\nexiftool.setExtensionsToExclude(extensionsToAdd)\n\n// Just removing file extensions\nexiftool.setExtensionsToExclude(null, extensionsToRemove)\n```\n\n### Exiftool Version and Location\nExiftool is [updated](https://exiftool.org/history.html) very frequently, so it might be useful to know which version is installed and being used by this package.  If a TAG is present in the image metadata, but not being returned in the query, the installed version of Exiftool might not know about it and need to be updated.  The install location and version of Exiftool are both queryable.  These are **Async/Await** methods.\n\n```javascript\nlet exiftool = new Exiftool()\nconsole.log(await exiftool.which())\n// /usr/local/bin/exiftool\nconsole.log(await exiftool.version())\n// 12.46\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattduffy%2Fexiftool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmattduffy%2Fexiftool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattduffy%2Fexiftool/lists"}