Scans the hierarchy of a parent node to find all descendant nodes matching specified types. Essential for identifying annotation targets, discovering components, or analyzing design structure.
Parameters
ID of the parent node to scan. The scan traverses all descendants recursively.
Array of Figma node type strings to match. Common types:
COMPONENT - Design system components
INSTANCE - Component instances
FRAME - Container frames
GROUP - Grouped elements
TEXT - Text layers
RECTANGLE - Rectangle shapes
ELLIPSE - Circle/ellipse shapes
POLYGON - Polygon shapes
STAR - Star shapes
LINE - Line shapes
VECTOR - Vector paths
SECTION - Section frames
Response
Returns an object with:
{
success : boolean ,
count : number ,
matchingNodes : Array <{
id : string ,
name : string ,
type : string ,
bbox : {
x : number ,
y : number ,
width : number ,
height : number
}
}>,
searchedTypes : string []
}
Find components and instances
Find all interactive elements
Find text layers
const result = await scan_nodes_by_types ({
nodeId: "frame-id" ,
types: [ "COMPONENT" , "INSTANCE" ]
});
console . log ( `Found ${ result . count } components/instances` );
result . matchingNodes . forEach ( node => {
console . log ( `- ${ node . name } ( ${ node . type } )` );
});
Finding Annotation Targets
The primary use case is identifying which nodes need annotations:
// 1. Scan for all potential annotation targets
const targets = await scan_nodes_by_types ({
nodeId: frameId ,
types: [ "COMPONENT" , "INSTANCE" , "FRAME" ]
});
// 2. Get existing annotations
const { annotations } = await get_annotations ({
nodeId: frameId ,
includeCategories: true
});
// 3. Find nodes that don't have annotations yet
const annotatedNodeIds = new Set ( annotations . map ( a => a . nodeId ));
const needsAnnotation = targets . matchingNodes . filter (
node => ! annotatedNodeIds . has ( node . id )
);
console . log ( ` ${ needsAnnotation . length } nodes need annotations` );
// 4. Create annotations for missing ones
const newAnnotations = needsAnnotation . map ( node => ({
nodeId: node . id ,
labelMarkdown: `** ${ node . name } ** \n\n Type: ${ node . type } `
}));
await set_multiple_annotations ({
nodeId: frameId ,
annotations: newAnnotations
});
Workflow Examples
Design system audit
Find all components to document:
// Scan for all components
const { matchingNodes } = await scan_nodes_by_types ({
nodeId: designSystemPageId ,
types: [ "COMPONENT" ]
});
// Group by naming convention
const byCategory = {};
matchingNodes . forEach ( node => {
const category = node . name . split ( '/' )[ 0 ]; // e.g., "Button/Primary"
if ( ! byCategory [ category ]) byCategory [ category ] = [];
byCategory [ category ]. push ( node );
});
console . log ( "Components by category:" , byCategory );
Interactive element discovery
Find all elements that need interaction specs:
const { matchingNodes } = await scan_nodes_by_types ({
nodeId: screenId ,
types: [ "INSTANCE" , "COMPONENT" ]
});
// Filter for interactive elements
const interactive = matchingNodes . filter ( node => {
const name = node . name . toLowerCase ();
return name . includes ( 'button' ) ||
name . includes ( 'input' ) ||
name . includes ( 'link' ) ||
name . includes ( 'toggle' );
});
console . log ( `Found ${ interactive . length } interactive elements` );
Layout analysis
Analyze frame structure:
const { matchingNodes } = await scan_nodes_by_types ({
nodeId: pageId ,
types: [ "FRAME" ]
});
// Find auto-layout frames (would need additional get_node_info calls)
const frames = matchingNodes . filter ( node =>
node . name . toLowerCase (). includes ( 'auto-layout' ) ||
node . name . toLowerCase (). includes ( 'stack' )
);
console . log ( `Found ${ frames . length } layout frames` );
Combining with Annotations
Complete annotation workflow
// Step 1: Find all annotation targets
const scan = await scan_nodes_by_types ({
nodeId: parentId ,
types: [ "COMPONENT" , "INSTANCE" , "FRAME" ]
});
// Step 2: Get categories
const { categories } = await get_annotations ({
nodeId: parentId ,
includeCategories: true
});
const designCategory = categories . find ( c => c . name === "Design" );
// Step 3: Build annotations
const annotations = scan . matchingNodes . map ( node => ({
nodeId: node . id ,
labelMarkdown: `** ${ node . name } ** \n\n ` +
`Type: ${ node . type } \n ` +
`Size: ${ node . bbox . width } × ${ node . bbox . height } px` ,
categoryId: designCategory . id
}));
// Step 4: Apply batch
await set_multiple_annotations ({
nodeId: parentId ,
annotations
});
Selective annotation by node type
// Find components only
const components = await scan_nodes_by_types ({
nodeId: frameId ,
types: [ "COMPONENT" ]
});
// Annotate with component-specific info
const componentAnnotations = components . matchingNodes . map ( comp => ({
nodeId: comp . id ,
labelMarkdown: `**Component** \n\n ` +
`Name: ${ comp . name } \n ` +
`[View in design system](https://ds.example.com)` ,
categoryId: "component-docs"
}));
// Find instances separately
const instances = await scan_nodes_by_types ({
nodeId: frameId ,
types: [ "INSTANCE" ]
});
// Annotate with instance-specific info
const instanceAnnotations = instances . matchingNodes . map ( inst => ({
nodeId: inst . id ,
labelMarkdown: `**Instance** \n\n Component: ${ inst . name } ` ,
categoryId: "usage-docs"
}));
// Apply both batches
await set_multiple_annotations ({
nodeId: frameId ,
annotations: [ ... componentAnnotations , ... instanceAnnotations ]
});
Spatial Analysis
The bounding box data enables spatial queries:
const { matchingNodes } = await scan_nodes_by_types ({
nodeId: frameId ,
types: [ "COMPONENT" , "INSTANCE" ]
});
// Find nodes in specific region
const topHalf = matchingNodes . filter ( node =>
node . bbox . y < 500
);
// Find large elements
const largeNodes = matchingNodes . filter ( node =>
node . bbox . width > 200 && node . bbox . height > 200
);
// Find elements by proximity to a point
function findClosest ( x , y , nodes ) {
return nodes
. map ( node => ({
node ,
distance: Math . hypot (
( node . bbox . x + node . bbox . width / 2 ) - x ,
( node . bbox . y + node . bbox . height / 2 ) - y
)
}))
. sort (( a , b ) => a . distance - b . distance )[ 0 ]. node ;
}
const closest = findClosest ( 100 , 100 , matchingNodes );
Performance
Scans recursively through entire node hierarchy
Returns immediately with full results (no chunking)
Efficient for finding specific node types in complex designs
For text-only scans, use scan_text_nodes instead (optimized with chunking)
Use Cases
Pre-annotation scanning
Identify all elements that need annotations before batch operations
Component inventory
Build a complete list of all components in a design system
Instance tracking
Find all instances of components to verify consistency
Layout structure analysis
Map out the frame hierarchy of a design
Element filtering
Find specific types of nodes for targeted operations
Related Tools
get_annotations Get existing annotations
set_multiple_annotations Batch annotate discovered nodes
scan_text_nodes Specialized tool for scanning text nodes
get_node_info Get detailed info about specific nodes