Preview: browse every icon now. Accounts, the API and MCP open once the set is proofread.

Documentation

Getting started

Not Boring Icons is 575 squircle icons on a 24px grid, in Stroke, Solid and Duotone. Copy them by hand from the library, fetch them over HTTP, or let your coding agent find and place them for you.

Quickstart

Three steps, about a minute:

terminal
curl https://not-boring-icons.vercel.app/api/v1/icons/arrow-right?style=stroke \
  -H "Authorization: Bearer YOUR_API_KEY"

You get back a plain SVG that uses currentColor, so it takes the text colour of wherever you put it. Keep the key in an environment variable (we use NBI_API_KEY in examples) and never ship it to the browser.

AI agents & MCP

Our MCP server lives at https://not-boring-icons.vercel.app/api/mcp. It speaks Streamable HTTP and authenticates with the same API key. Once it's added, ask your agent for UI as usual. It will search the library by meaning and write real components.

Claude Code

terminal
claude mcp add --transport http not-boring-icons https://not-boring-icons.vercel.app/api/mcp \
  --header "Authorization: Bearer YOUR_API_KEY"

Cursor

Add this to ~/.cursor/mcp.json (or .cursor/mcp.json in a project):

mcp.json
{
  "mcpServers": {
    "not-boring-icons": {
      "url": "https://not-boring-icons.vercel.app/api/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

VS Code

.vscode/mcp.json
{
  "servers": {
    "not-boring-icons": {
      "type": "http",
      "url": "https://not-boring-icons.vercel.app/api/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Claude Desktop & stdio-only clients

Clients that only speak stdio can bridge with mcp-remote:

claude_desktop_config.json
{
  "mcpServers": {
    "not-boring-icons": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://not-boring-icons.vercel.app/api/mcp",
        "--header",
        "Authorization: Bearer YOUR_API_KEY"
      ]
    }
  }
}

Tools

ToolWhat it does
search_iconsFind icons by meaning: query, optional category, limit (default 12).
get_iconOne icon as svg, jsx or vue, with style, size, strokeWidth, color.
get_iconsUp to 30 icons at once in the same style and format, for toolbars and nav bars.
list_categoriesThe 30 categories with counts.

The agent prompt

No MCP support? Paste this into your agent's instructions (CLAUDE.md, AGENTS.md, Cursor rules, a system prompt…). It teaches the agent to use the REST API and to keep icons consistent.

instructions for your agent
Use Not Boring Icons for every icon in this project — never hand-draw SVGs or mix in another icon set.

How to get icons:
- Search: GET https://not-boring-icons.vercel.app/api/v1/icons?q=<plain words>   (e.g. q=delete, q=upload cloud)
- Fetch:  GET https://not-boring-icons.vercel.app/api/v1/icons/<name>?style=stroke&format=jsx   (format: svg | jsx | vue)
- Auth:   send the header "Authorization: Bearer $NBI_API_KEY" (the key lives in the NBI_API_KEY env var; never commit it)

Rules:
- Save each icon once as a component (React: components/icons/<Name>Icon.tsx) and reuse it.
- Icons are 24×24 and use currentColor. Stroke width 2 at 24px, 1.75 at 20px, 1.5 at 16px.
- Pick names by meaning; if a search returns nothing, try a broader word before falling back.
- Full docs for agents: https://not-boring-icons.vercel.app/llms.txt

Agents can also read /llms.txt, a plain-text version of these docs made for them.

REST API

Base URL https://not-boring-icons.vercel.app/api/v1. Send your key as Authorization: Bearer nbi_… (or X-Api-Key). Every response is CORS-enabled, but keep keys server-side.

GET /icons

Search the catalogue. Returns names and metadata, no artwork.

ParamDefaultNotes
q—Plain words. delete finds trash, ai chat finds ai-chat.
category—Exact category name, e.g. Arrows.
limit50Up to 200.
search
curl "https://not-boring-icons.vercel.app/api/v1/icons?q=upload" \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /icons/:name

One icon, rendered to order.

ParamDefaultNotes
stylestrokestroke · solid · duotone (solid & duotone need Pro)
formatsvgsvg · jsx · vue · json
size24Width/height in px (8–512). The viewBox is always 24.
stroke2Stroke width (0.5–3). Ignored for solid.
colorcurrentColorAny CSS colour; hex without # works too.
React component
curl "https://not-boring-icons.vercel.app/api/v1/icons/folder-open?format=jsx" \
  -H "Authorization: Bearer $NBI_API_KEY" > components/icons/FolderOpenIcon.jsx

React, Vue, HTML

The simplest durable setup: fetch the icons you use once, commit them as components, and let your bundler do the rest. A tiny script keeps them in sync:

scripts/icons.mjs
// node scripts/icons.mjs pulls the icons your app uses into components/icons
import { writeFile, mkdir } from "node:fs/promises";

const ICONS = ["home-01", "search-01", "bell-ring", "settings-01", "trash"];
const headers = { Authorization: `Bearer ${process.env.NBI_API_KEY}` };

await mkdir("components/icons", { recursive: true });
for (const name of ICONS) {
  const res = await fetch(`https://not-boring-icons.vercel.app/api/v1/icons/${name}?format=jsx`, { headers });
  if (!res.ok) throw new Error(`${name}: ${(await res.json()).error.message}`);
  const file = name.split("-").map(w => w[0].toUpperCase() + w.slice(1)).join("") + "Icon.jsx";
  await writeFile(`components/icons/${file}`, await res.text());
}

Every component accepts size plus any SVG prop (className, strokeWidth, aria-label…). For plain HTML, paste the SVG and colour it with CSS color.

Animated icons

Preview the animated icon collection. Static Stroke icons remain free; animated exports require Pro or Lifetime. Download SVG, React or Vue from the gallery when signed in, or use an API key through REST and MCP. Each animation plays once on hover or keyboard focus and respects reduced motion.

With MCP, call list_animated_icons to discover names, durations and byte sizes, then get_animated_icon with a name and format: "jsx", "vue" or "svg". Use get_animated_icons for up to 30 names at once. Free keys can discover the collection but cannot export animated code.

Animated icon API
curl "https://not-boring-icons.vercel.app/api/v1/animated/analytics?format=jsx" \
  -H "Authorization: Bearer $NBI_API_KEY"

GET /api/v1/animated lists the collection. Individual exports accept format=svg|jsx|vue|json, size, stroke and color. The collection uses Stroke geometry. Unsupported animated names return 404 and Free keys receive 402 with pro_animation.

Trigger from a whole button
<button data-nbi-trigger aria-label="Analytics">
  <AnalyticsAnimatedIcon size={24} />
</button>

Paste SVG inline, rather than loading it through an image tag. Hover the icon itself, or add data-nbi-trigger to its containing button or link. Keyboard focus plays the same gesture; there is no autoplay or looping. Leaving early resets to the resting icon. Repeat the interaction to replay. SVG and exported components contain scoped CSS and need no player or JavaScript dependency. React components accept size, strokeWidth, color and standard SVG props. Use the containing control for the accessible label.

Sizes & stroke

Icons are drawn at 24px with a 2px stroke. Scale the stroke with the icon so small sizes don't clog up:

Icon sizeStrokeUse for
24px2Default UI, toolbars, empty states
20px1.75Buttons, inputs, list rows
16px1.5Dense tables, inline with small text

Figma

Pro and Lifetime members get the Figma library: every icon as a component with a Style variant, stroke width bound to a variable (2 / 1.75 / 1.5 modes) and colour bound to icon/foreground. Swap styles from the properties panel; nothing moves.

Limits & errors

Free keys get 1,000 requests a day, Pro and Lifetime get 50,000. Limits reset at 00:00 UTC. Responses carry X-RateLimit-Limit and X-RateLimit-Remaining. Errors are JSON:

error
{ "error": { "code": "pro_style", "message": "The solid style is part of Pro…", "docs": "https://not-boring-icons.vercel.app/docs" } }
StatusCodeMeaning
401missing_key / invalid_keyNo key, a typo, or a revoked key.
402pro_styleSolid/duotone with a free key.
404not_foundUnknown icon. The message suggests close matches.
429rate_limitedDaily limit reached.

License

With any account you may use the icons in personal and commercial projects (apps, websites, products, client work, marketing) with no attribution required. You may not resell or redistribute the icons as an icon set, font or competing library, or share your API key outside your team. Pro styles require an active Pro or Lifetime plan at the time you add them to a project; icons you shipped stay licensed.