A TypeScript library for extracting metadata and downloading images from Figma files programmatically, based on Figma-Context-MCP.
npm install figma-metadata-extractor- 🎨 Extract comprehensive metadata from Figma files
- 📦 Auto-download image assets (to disk or as buffers)
- 🔄 Support for both file-based and buffer-based workflows
- 🎯 Enrich metadata with image paths and markup
- 🔐 Support for both API keys and OAuth tokens
- 📝 Multiple output formats (JSON, YAML, object)
import { getFigmaMetadata } from "figma-metadata-extractor";
// Extract metadata AND automatically download image assets to disk
const metadata = await getFigmaMetadata(
"https://figma.com/file/ABC123/My-Design",
{
apiKey: "your-figma-api-key",
outputFormat: "object",
downloadImages: true, // Auto-download image assets
localPath: "./assets/images", // Where to save images
},
);
// Nodes are enriched with downloadedImage property
metadata.nodes.forEach((node) => {
if (node.downloadedImage) {
console.log(node.downloadedImage.filePath);
console.log(node.downloadedImage.markdown); // 
}
});import {
getFigmaMetadata,
enrichMetadataWithImages,
} from "figma-metadata-extractor";
import fs from "fs/promises";
// Get metadata with images as ArrayBuffers
const result = await getFigmaMetadata(
"https://figma.com/file/ABC123/My-Design",
{
apiKey: "your-figma-api-key",
downloadImages: true,
returnBuffer: true, // Get images as ArrayBuffer
},
);
// Images are returned separately, metadata is not enriched
console.log(`Downloaded ${result.images.length} images as buffers`);
// Process buffers (upload to S3, convert format, etc.)
const savedPaths: string[] = [];
for (const image of result.images) {
// Example: Save to disk after processing
const buffer = Buffer.from(image.buffer);
const path = `./processed/${Date.now()}.png`;
await fs.writeFile(path, buffer);
savedPaths.push(path);
}
// Optionally enrich metadata with saved file paths
const enrichedMetadata = enrichMetadataWithImages(result, savedPaths, {
useRelativePaths: true,
});
// Now nodes have downloadedImage properties
enrichedMetadata.nodes.forEach((node) => {
if (node.downloadedImage) {
console.log(node.downloadedImage.markdown);
}
});import { getFigmaMetadata } from "figma-metadata-extractor";
// Extract metadata from a Figma file
const metadata = await getFigmaMetadata(
"https://figma.com/file/ABC123/My-Design",
{
apiKey: "your-figma-api-key",
outputFormat: "object", // or 'json' or 'yaml'
},
);
console.log(metadata.nodes); // Array of design nodes
console.log(metadata.globalVars); // Styles, colors, etc.
// Download images from the file
const images = await downloadFigmaImages(
"https://figma.com/file/ABC123/My-Design",
[
{
nodeId: "1234:5678",
fileName: "icon.svg",
},
{
nodeId: "9876:5432",
fileName: "hero-image.png",
},
],
{
apiKey: "your-figma-api-key",
localPath: "./assets/images",
},
);
console.log(images); // Array of download results
// Download a single frame image from a Figma URL
const frameImage = await downloadFigmaFrameImage(
"https://figma.com/file/ABC123/My-Design?node-id=1234-5678",
{
apiKey: "your-figma-api-key",
localPath: "./assets/frames",
fileName: "my-frame.png",
format: "png", // or 'svg'
pngScale: 2,
},
);
console.log(frameImage.filePath); // Path to downloaded imageExtracts comprehensive metadata from a Figma file including layout, content, visuals, and component information.
Parameters:
figmaUrl(string): The Figma file URLoptions(FigmaMetadataOptions): Configuration options
Options:
apiKey?: string- Figma API key (Personal Access Token). Either apiKey or oauthToken is requiredoauthToken?: string- Figma OAuth Bearer token. When provided, OAuth is used automaticallyoutputFormat?: 'json' | 'yaml' | 'object'- Output format (default: 'object')depth?: number- Maximum depth to traverse the node treedownloadImages?: boolean- Automatically download image assets and enrich metadata (default: false)localPath?: string- Local path for downloaded images (optional if returnBuffer is true)imageFormat?: 'png' | 'svg'- Image format for downloads (default: 'png')pngScale?: number- Export scale for PNG images (default: 2)returnBuffer?: boolean- Return images as ArrayBuffer instead of saving to disk (default: false)enableLogging?: boolean- Enable JSON debug log files (default: false)
Returns: Promise<FigmaMetadataResult | string>
FigmaMetadataResult:
{
metadata: any; // File metadata
nodes: any[]; // Design nodes
globalVars: any; // Styles, colors, etc.
images?: FigmaImageResult[]; // Only present when downloadImages: true and returnBuffer: true
}When downloadImages: true and returnBuffer: false, nodes with image assets will include a downloadedImage property:
{
filePath: string; // Absolute path
relativePath: string; // Relative path for code
dimensions: {
width, height;
}
markdown: string; // 
html: string; // <img src="..." />
}When downloadImages: true and returnBuffer: true, images are returned in the images array and nodes are NOT enriched. Use enrichMetadataWithImages() to enrich them later after saving buffers to disk.
Downloads SVG and PNG images from a Figma file.
Parameters:
figmaUrl(string): The Figma file URLnodes(FigmaImageNode[]): Array of image nodes to downloadoptions(FigmaMetadataOptions & FigmaImageOptions): Configuration options
Node Properties:
nodeId: string- The Figma node ID (format: '1234:5678')fileName: string- Local filename (must end with .png or .svg)imageRef?: string- Image reference for image fillsneedsCropping?: boolean- Whether image needs croppingcropTransform?: number[][]- Transform matrix for croppingrequiresImageDimensions?: boolean- Whether to generate CSS variablesfilenameSuffix?: string- Suffix for unique filenames
Additional Options:
pngScale?: number- Export scale for PNG images (default: 2)localPath?: string- Absolute path to save images (optional if returnBuffer is true)returnBuffer?: boolean- Return images as ArrayBuffer instead of saving to disk (default: false)enableLogging?: boolean- Enable JSON debug log files (default: false)
Returns: Promise<FigmaImageResult[]>
When returnBuffer is true, each result will contain a buffer property instead of filePath.
Enriches metadata with saved image file paths after saving buffers to disk.
Parameters:
metadata(FigmaMetadataResult): The metadata result from getFigmaMetadata with returnBuffer: trueimagePaths(string[]): Array of file paths where images were saved (must match order of metadata.images)options(object): Configuration optionsuseRelativePaths?: boolean | string- How to generate paths (default: true)localPath?: string- Base path for relative path calculation
Returns: FigmaMetadataResult with enriched nodes
Example:
// Get metadata with buffers
const result = await getFigmaMetadata(url, {
apiKey: "key",
downloadImages: true,
returnBuffer: true,
});
// Save buffers to disk
const paths = await Promise.all(
result.images.map((img, i) =>
fs
.writeFile(`./images/img-${i}.png`, Buffer.from(img.buffer))
.then(() => `./images/img-${i}.png`),
),
);
// Enrich metadata with file paths
const enriched = enrichMetadataWithImages(result, paths, {
useRelativePaths: true,
});Downloads a single frame image from a Figma URL that contains a node-id parameter.
Parameters:
figmaUrl(string): The Figma URL with node-id parameter (e.g.,https://figma.com/file/ABC123/My-Design?node-id=1234-5678)options(FigmaFrameImageOptions): Configuration options
Options:
apiKey?: string- Figma API key (Personal Access Token). Either apiKey or oauthToken is requiredoauthToken?: string- Figma OAuth Bearer token. When provided, OAuth is used automaticallylocalPath?: string- Absolute path to save the image (optional if returnBuffer is true)fileName?: string- Local filename (must end with .png or .svg, optional if returnBuffer is true)format?: 'png' | 'svg'- Image format to download (default: 'png')pngScale?: number- Export scale for PNG images (default: 2)returnBuffer?: boolean- Return image as ArrayBuffer instead of saving to disk (default: false)enableLogging?: boolean- Enable JSON debug log files (default: false)
Returns: Promise
Result Properties:
filePath?: string- Path to saved file (only when returnBuffer is false)buffer?: ArrayBuffer- Image data as ArrayBuffer (only when returnBuffer is true)finalDimensions: { width: number; height: number }- Image dimensionswasCropped: boolean- Whether the image was croppedcssVariables?: string- CSS variables for dimensions (if requested)
You need either a Figma API key (Personal Access Token) or an OAuth token:
- Go to Figma → Settings → Account → Personal Access Tokens
- Generate a new token
- Use it in the
apiKeyoption
getFigmaMetadata(url, { apiKey: "figd_xxx..." });- Set up Figma OAuth in your application
- Use the bearer token in the
oauthTokenoption
getFigmaMetadata(url, { oauthToken: "figu_xxx..." });Note: When oauthToken is provided, OAuth (Bearer auth) is used automatically. If both apiKey and oauthToken are provided, oauthToken takes precedence.
The easiest way to download a frame image is to copy the Figma URL directly from your browser when viewing a specific frame:
import { downloadFigmaFrameImage } from "figma-metadata-extractor";
// Copy this URL from Figma when viewing a frame
const figmaUrl =
"https://www.figma.com/design/ABC123/My-Design?node-id=1234-5678&t=xyz123";
// Save to disk
const result = await downloadFigmaFrameImage(figmaUrl, {
apiKey: "your-figma-api-key",
localPath: "./downloads",
fileName: "my-frame.png",
format: "png",
pngScale: 2, // High resolution
});
console.log(`Downloaded to: ${result.filePath}`);
console.log(
`Dimensions: ${result.finalDimensions.width}x${result.finalDimensions.height}`,
);If you want to process the image in memory without saving to disk:
import { downloadFigmaFrameImage } from "figma-metadata-extractor";
const figmaUrl =
"https://www.figma.com/design/ABC123/My-Design?node-id=1234-5678";
// Get as ArrayBuffer
const result = await downloadFigmaFrameImage(figmaUrl, {
apiKey: "your-figma-api-key",
returnBuffer: true,
format: "png",
});
console.log(`Buffer size: ${result.buffer.byteLength} bytes`);
console.log(
`Dimensions: ${result.finalDimensions.width}x${result.finalDimensions.height}`,
);
// Use the buffer directly (e.g., upload to cloud storage, process with sharp, etc.)
// const processedImage = await sharp(Buffer.from(result.buffer)).resize(100, 100).toBuffer();import { downloadFigmaImages } from "figma-metadata-extractor";
// For multiple frames, use the batch download function
const results = await downloadFigmaImages(
"https://figma.com/file/ABC123/My-Design",
[
{ nodeId: "1234:5678", fileName: "frame1.png" },
{ nodeId: "9876:5432", fileName: "frame2.svg" },
{ nodeId: "1111:2222", fileName: "frame3.png" },
],
{
apiKey: "your-figma-api-key",
localPath: "./frames",
},
);import { downloadFigmaImages } from "figma-metadata-extractor";
// Get multiple images as ArrayBuffers
const results = await downloadFigmaImages(
"https://figma.com/file/ABC123/My-Design",
[
{ nodeId: "1234:5678", fileName: "frame1.png" },
{ nodeId: "9876:5432", fileName: "frame2.png" },
],
{
apiKey: "your-figma-api-key",
returnBuffer: true,
},
);
// Process each buffer
results.forEach((result, index) => {
console.log(`Image ${index}: ${result.buffer.byteLength} bytes`);
// Upload to S3, process with sharp, etc.
});The library also exports the underlying extractor system for custom processing:
import {
simplifyRawFigmaObject,
allExtractors,
layoutExtractor,
textExtractor,
} from "figma-metadata-extractor";
// Use specific extractors
const customResult = simplifyRawFigmaObject(rawFigmaResponse, [
layoutExtractor,
textExtractor,
]);MIT