The Figma API allows you to programmatically access Figma designs, extract components, read styles, and export assets. This comprehensive guide covers everything you need to know.
Getting Started
Authentication
# Get your personal access token from Figma Settings
# Settings > Account > Personal Access Tokens
# Use in requests
curl -H "X-Figma-Token: YOUR_ACCESS_TOKEN" \
https://api.figma.com/v1/me
Base URL
https://api.figma.com/v1
Getting File Data
Fetch File
# Get entire file
curl -H "X-Figma-Token: $TOKEN" \
"https://api.figma.com/v1/files/FILE_KEY"
# Get specific nodes
curl -H "X-Figma-Token: $TOKEN" \
"https://api.figma.com/v1/files/FILE_KEY/nodes?ids=NODE_ID_1,NODE_ID_2"
Node Types
{
"id": "1:2",
"name": "Button",
"type": "COMPONENT",
"children": [...],
"absoluteBoundingBox": {
"x": 0,
"y": 0,
"width": 120,
"height": 40
},
"fills": [...],
"strokes": [...],
"effects": [...],
"cornerRadius": 8,
"componentId": "..."
}
JavaScript Client
Basic Client
class FigmaClient {
constructor(accessToken) {
this.token = accessToken;
this.baseUrl = 'https://api.figma.com/v1';
}
async request(endpoint, options = {}) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
'X-Figma-Token': this.token,
...options.headers
}
});
if (!response.ok) {
throw new Error(`Figma API Error: ${response.status}`);
}
return response.json();
}
// Get file
async getFile(fileKey) {
return this.request(`/files/${fileKey}`);
}
// Get specific nodes
async getFileNodes(fileKey, nodeIds) {
return this.request(
`/files/${fileKey}/nodes?ids=${nodeIds.join(',')}`
);
}
// Get components
async getComponents(fileKey) {
return this.request(`/files/${fileKey}/components`);
}
// Get styles
async getStyles(fileKey) {
return this.request(`/files/${fileKey}/styles`);
}
}
Extracting Components
Get All Components
async function extractComponents(client, fileKey) {
const data = await client.getFile(fileKey);
const components = [];
function traverse(node) {
if (node.type === 'COMPONENT' || node.type === 'COMPONENT_SET') {
components.push({
id: node.id,
name: node.name,
description: node.description,
type: node.type
});
}
if (node.children) {
node.children.forEach(traverse);
}
}
data.document.children.forEach(traverse);
return components;
}
Get Component Details
async function getComponentDetails(client, fileKey, componentId) {
const data = await client.getFileNodes(fileKey, [componentId]);
const node = data.nodes[componentId];
return {
name: node.name,
bounds: node.absoluteBoundingBox,
fills: node.fills,
strokes: node.strokes,
effects: node.effects,
cornerRadius: node.cornerRadius,
blendMode: node.blendMode,
opacity: node.opacity,
children: node.children?.map(child => ({
name: child.name,
type: child.type,
fills: child.fills
}))
};
}
Extracting Styles
Get All Styles
async function extractStyles(client, fileKey) {
const { meta } = await client.getStyles(fileKey);
const styles = {
fill: [],
text: [],
effect: [],
stroke: []
};
for (const [key, style] of Object.entries(meta.styles)) {
styles[style.styleType.toLowerCase()].push({
id: key,
name: style.name,
description: style.description
});
}
return styles;
}
Style Properties
function getStyleProperties(node) {
return {
fill: node.fills?.map(f => ({
type: f.type,
color: f.color,
opacity: f.opacity
})),
stroke: node.strokes?.map(s => ({
type: s.type,
color: s.color
})),
text: node.style ? {
fontFamily: node.style.fontFamily,
fontSize: node.style.fontSize,
fontWeight: node.style.fontWeight,
lineHeightPx: node.style.lineHeightPx,
letterSpacing: node.style.letterSpacing
} : null,
effect: node.effects
};
}
Exporting Assets
Export Images
async function exportImages(client, fileKey, nodeIds, options = {}) {
const { images } = await client.request(
`/images/${fileKey}?ids=${nodeIds.join(',')}&format=png&scale=2`
);
return images;
}
// Usage
const images = await exportImages(
client,
'FILE_KEY',
['1:2', '3:4'],
{ format: 'png', scale: 2 }
);
// Download each
for (const [nodeId, url] of Object.entries(images)) {
const response = await fetch(url);
const buffer = await response.arrayBuffer();
// Save to file...
}
Export SVG
// Get SVG
const { images } = await client.request(
`/images/${file_KEY}?ids=NODE_ID&format=svg`
);
// Save SVG content
const svgResponse = await fetch(images[NODE_ID]);
const svgContent = await svgResponse.text();
Export Code
// Get code representation
const { code } = await client.request(
`/files/${fileKey}/nodes?ids=${nodeId}&code=true&format=html`
);
Webhooks
Register Webhook
curl -X POST "https://api.figma.com/v2/webhooks" \
-H "X-Figma-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_type": "FILE_NODE_CHANGED",
"client_id": "YOUR_CLIENT_ID",
"endpoint_url": "https://your-server.com/webhook",
"description": "Notify on file changes"
}'
Webhook Events
FILE_NODE_CHANGED- Node changedFILE_COMMENT- New commentFILE_VERSION_UPLOADED- Version uploaded
// Webhook handler
app.post('/webhook', (req, res) => {
const event = req.body;
switch (event.event_type) {
case 'FILE_NODE_CHANGED':
handleNodeChange(event);
break;
case 'FILE_COMMENT':
handleComment(event);
break;
}
res.status(200).send('OK');
});
Design to Code Example
Extract Component for Code
async function componentToCode(client, fileKey, componentId) {
const { nodes } = await client.getFileNodes(fileKey, [componentId]);
const node = nodes[componentId];
const code = {
name: node.name,
width: node.absoluteBoundingBox.width,
height: node.absoluteBoundingBox.height,
styles: {
backgroundColor: extractFillColor(node.fills),
borderRadius: node.cornerRadius,
boxShadow: extractShadow(node.effects)
},
children: node.children?.map((child, index) => ({
name: child.name,
type: child.type,
...getElementCode(child)
}))
};
return code;
}
function extractFillColor(fills) {
const fill = fills?.find(f => f.type === 'SOLID');
if (!fill) return null;
const { r, g, b } = fill.color;
const a = fill.opacity ?? 1;
return `rgba(${Math.round(r*255)}, ${Math.round(g*255)}, ${Math.round(b*255)}, ${a})`;
}
Real-World Examples
Generate CSS Variables
async function generateCSSVariables(client, fileKey) {
const styles = await extractStyles(client, fileKey);
let css = ':root {\n';
// Colors
for (const [name, style] of Object.entries(styles.fill)) {
css += ` --color-${name}: ${style.value};\n`;
}
// Typography
css += '\n /* Typography */\n';
for (const [name, style] of Object.entries(styles.text)) {
css += ` --font-${name}: ${style.value};\n`;
}
css += '}';
return css;
}
Build Component Library
async function buildComponentLibrary(client, fileKey) {
const components = await extractComponents(client, fileKey);
const library = { components: [] };
for (const component of components) {
const details = await getComponentDetails(client, fileKey, component.id);
library.components.push({
name: component.name,
category: extractCategory(component.name),
props: extractProps(details),
code: await generateReactCode(details)
});
}
return library;
}
Rate Limits
// API Rate limits
// - GET requests: 200/minute
// - Write requests: 200/minute
// - Bulk export: 500 images/minute
const rateLimit = {
remaining: response.headers.get('X-RateLimit-Remaining'),
reset: response.headers.get('X-RateLimit-Reset')
};
External Resources
Conclusion
The Figma API enables powerful design automation. Key points:
- Use Personal Access Token for authentication
- Fetch files, components, styles programmatically
- Export images and SVGs in various formats
- Set up webhooks for real-time updates
- Build design-to-code pipelines
Common use cases: design system documentation, asset exports, design-to-code, design analysis, and automation.
Comments