Skip to main content

Overview

Pagination

Handle paginated responses from the Figma REST API efficiently.

Some Figma API endpoints return paginated responses when the result set is large. This guide explains how to work with cursor-based pagination.

How Pagination Works

Paginated endpoints include a pagination object in the response with a cursor for the next page:

{
  "meta": {
    "components": [
      { "key": "abc123", "name": "Button" },
      { "key": "def456", "name": "Input" }
    ]
  },
  "pagination": {
    "cursor": "eyJpZCI6IjEyMzQ1In0=",
    "page_size": 30
  }
}

Fetching All Pages

Pass the cursor as a query parameter to get the next page. When cursor is null or absent, you’ve reached the end.

async function fetchAllComponents(fileKey: string, token: string) {
  const components = [];
  let cursor: string | undefined;

  do {
    const url = new URL(`https://api.figma.com/v1/files/${fileKey}/components`);
    if (cursor) url.searchParams.set("cursor", cursor);

    const response = await fetch(url.toString(), {
      headers: { "X-Figma-Token": token },
    });
    const data = await response.json();

    components.push(...data.meta.components);
    cursor = data.pagination?.cursor ?? undefined;
  } while (cursor);

  return components;
}

Pagination Parameters

ParameterTypeDescription
cursorstringOpaque cursor from the previous response
page_sizenumberNumber of items per page (default: 30, max: 100)

Cursors are opaque strings — don’t try to parse or construct them. Always use the exact cursor value from the API response.

Paginated Endpoints

Not all endpoints support pagination. Here are the ones that do:

EndpointReturns
/v1/files/:key/componentsPublished components
/v1/files/:key/component_setsComponent sets
/v1/files/:key/stylesPublished styles
/v1/files/:key/commentsComments
/v2/webhooksWebhook subscriptions
/v1/files/:key/variables/localLocal variables

Best Practices

Always implement pagination handling, even if your current files return small result sets. Files grow over time, and hard-coding single-page assumptions will break.

  • Set a reasonable page_size — Use 50-100 for batch operations
  • Handle rate limits between pages — Add a small delay if processing many pages
  • Stream results — Process each page as it arrives rather than collecting everything in memory
  • Cache cursors — If your integration supports resumable sync, store the last cursor

For large-scale operations, combine pagination with the /files/:key/nodes endpoint to fetch only the nodes you need, rather than downloading the entire file tree.