Skip to content
onyxaxPublic

About

HyLab — The Icons API for modern apps. 18,000+ icons from 10 sources (Tabler, Lucide, Heroicons, Phosphor, Remix, Carbon, Iconoir, BoxIcons, CSS.gg, Octicons). Fully customizable via URL: change color, size, stroke, and format (SVG/PNG/WebP). Free, open source, no auth required. Drop a URL into any project and get beautiful icons instantly.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

HyLab

HyLab

The Icons API for Modern Apps

26,150 icons · 11 families · One endpoint — any color, size, or format.

Live Stars Icons MIT

Deploy with Vercel



HyLab — Browse 18k icons


Quick Start

No install — just a URL. Works with curl, HTML, React, Next.js, Vue, Svelte, Python.

# curl — SVG
curl "https://hylab.vercel.app/api/icons/home?color=7c9a82&size=32"

# curl — PNG
curl "https://hylab.vercel.app/api/icons/home?color=7c9a82&size=64&format=png"

# curl — filter by family + category
curl "https://hylab.vercel.app/api/icons?set=tabler&category=navigation&limit=20"
<!-- HTML — drop in anywhere -->
<img src="https://hylab.vercel.app/api/icons/home?color=7c9a82&size=32" alt="Home" />
<img src="https://hylab.vercel.app/api/icons/heart?color=ef4444&size=24" alt="Heart" />
// React — zero deps
const Icon = ({ name, color = "7c9a82", size = 24 }: { name: string; color?: string; size?: number }) => (
  <img src={`https://hylab.vercel.app/api/icons/${name}?color=${color}&size=${size}`} alt={name} />
);

Features

One API, All Icons

One endpoint serves 11 families. No need to install 11 packages.

Fully Customizable

?color=7c9a82&size=32&stroke=2&format=svg — color, size, stroke, format.

SVG, PNG & WebP

Vector for web, raster for email. sharp on the edge, immutable cache.

No Auth, No Limits

Free, open source, CORS *. No API keys.

Filter by Family

?set=tabler or ?set=lucide — isolate one family. Combines with ?category=.

Shareable URLs

/browse?set=tabler&category=navigation — every filter is in the URL.


API Reference

Get Icon

GET /api/icons/:name
Parameter Type Default Description
name path — Icon name — home, search, heart
color query currentColor Hex without # — 7c9a82
size query 24 Pixels 1–512
stroke query 2 Stroke 0.5–4
fill query false true to fill shape
format query svg svg · png · webp
curl "https://hylab.vercel.app/api/icons/home?color=7c9a82&size=32"
curl "https://hylab.vercel.app/api/icons/home?format=png&size=64"
curl "https://hylab.vercel.app/api/icons/home?color=7c9a82&size=48&stroke=3&format=webp"

List Icons

GET /api/icons?page=1&limit=20&category=navigation&set=tabler
Parameter Type Default Description
page query 1 Page number
limit query 50 Items per page — max 100
category query — navigation, action, media… (14 total)
set query — Family — tabler, lucide, phosphor… (alias source)

Search

GET /api/icons/search?q=arrow

Categories

GET /api/icons/categories
GET /api/icons/categories?set=tabler

Filter counts to a family.

Sets

GET /api/icons/sets
GET /api/icons/sets?category=navigation

Filter families to a category.

Status

GET /api/status

Live probes to 5 endpoints — avgResponseTime, services[], uptime.


Code Examples

HTML — copy & paste
<img src="https://hylab.vercel.app/api/icons/home?color=7c9a82&size=32" alt="Home" />
<img src="https://hylab.vercel.app/api/icons/search?color=ffffff&size=24" alt="Search" />
<img src="https://hylab.vercel.app/api/icons/heart?color=ef4444&size=48&format=png" alt="Heart" />

<!-- Family filter -->
<img src="https://hylab.vercel.app/api/icons/home?color=7c9a82&size=32" alt="Home" />
React — zero deps
function Icon({ name, color = "7c9a82", size = 24 }: { name: string; color?: string; size?: number }) {
  return <img src={`https://hylab.vercel.app/api/icons/${name}?color=${color}&size=${size}`} alt={name} />;
}

// Family filtered list
function TablerIcons() {
  const [icons, setIcons] = useState([]);
  useEffect(() => {
    fetch('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/api/icons?set=tabler&limit=20').then(r => r.json()).then(d => setIcons(d.data));
  }, []);
  return icons.map(i => <Icon key={i.name} name={i.name} />);
}
Next.js — edge proxy
// app/icon/[name]/route.ts
import { NextResponse } from "next/server";
export async function GET(req: Request, { params }: { params: { name: string } }) {
  const { searchParams } = new URL(req.url);
  const color = searchParams.get("color") || "7c9a82";
  const set = searchParams.get("set") || "tabler";
  const res = await fetch(`https://hylab.vercel.app/api/icons/${params.name}?color=${color}&set=${set}`);
  return new NextResponse(await res.blob(), {
    headers: { "Content-Type": "image/svg+xml", "Cache-Control": "public, max-age=86400" },
  });
}
Vue
<template><span v-html="svg" /></template>
<script setup>
import { ref, onMounted } from "vue";
const svg = ref("");
onMounted(async () => {
  const res = await fetch(`/api/icons/home?color=7c9a82&size=32&set=lucide`);
  svg.value = await res.text();
});
</script>
Svelte
<script>
  export let name = "home";
  let svg = "";
  $: fetch(`/api/icons/${name}?color=7c9a82&set=tabler`).then(r=>r.text()).then(t=>svg=t);
</script>
<span>{@html svg}</span>
Python
import requests

# Family filtered
res = requests.get("https://hylab.vercel.app/api/icons", params={"set": "tabler", "limit": 20})
icons = res.json()["data"]

# Single icon
svg = requests.get("https://hylab.vercel.app/api/icons/home", params={"color": "7c9a82", "size": "32"}).text

# Search
icons = requests.get("https://hylab.vercel.app/api/icons/search", params={"q": "arrow"}).json()["data"]

Icon Sources

Source Icons License
SF Symbols 8,111 Apple SF Symbols Agreement
Tabler 5,093 MIT
Remix 3,229 Apache 2.0
Carbon 2,665 Apache 2.0
Lucide 1,582 ISC
Phosphor 1,512 MIT
Iconoir 1,383 MIT
BoxIcons 814 MIT
Octicons 733 MIT
CSS.gg 704 MIT
Heroicons 324 MIT

Total: 26,150 icons · 14 categories · Shareable /browse?set=sfsymbols&category=navigation


Tech Stack

Next.js TypeScript Tailwind Vercel


Self-Host

git clone https://github.com/onyxax/HyLab.git
cd HyLab
npm install
npm run dev
# http://localhost:3000

Status Page — Real History

/status is backed by real probes and a real database — no mock data, no fabricated uptime.

  • 5 live probes (SVG, PNG, search, categories, list) run in parallel on every page view and every cron tick.
  • Permanent history in Postgres (Supabase) — schema hylab_status:
    • daily — per-day, per-service buckets (ok, fail, ms_sum, ms_max, last_fail_at)
    • runs — log of every probe batch (kept 30 days)
    • incidents — outage windows with open/close timestamps
  • Uptime timeline — a continuous segmented strip (7D / 90D / 12M). Every slot is a real period: green = operational, amber = degraded, red = outage, hollow = no probes yet. Click a slot for its exact numbers.
  • Uptime everywhere — the overall card shows 7d / 90d / all-time, and every service row carries its own 7d and 90d uptime plus the probe count behind it.
  • Honest gaps — days without probes render as an empty slot, never as a fake 100%.
  • Daily cron (/api/cron/probe) records even with no visitors, and .github/workflows/status-probe.yml fires the same probe every 15 minutes so the history fills in fast.

Setup

cp .env.example .env.local
# DATABASE_URL=postgresql://[ROLE].[PROJECT-REF]:[PASSWORD]@aws-[INDEX]-[REGION].pooler.supabase.com:6543/postgres
# CRON_SECRET=<long random string>

The 15-minute GitHub workflow needs no secret — it calls the public /api/status endpoint, which performs the same real measurement and records it. (CRON_SECRET only protects the lighter /api/cron/probe route that the Vercel Cron job calls.)

The connecting role only needs access to the hylab_status schema:

create schema if not exists hylab_status;
-- tables: daily / runs / incidents  (see src/domain/status/db.ts)
grant usage on schema hylab_status to hylab_status;
grant select, insert, update on hylab_status.daily to hylab_status;
grant select, insert on hylab_status.runs to hylab_status;
grant delete on hylab_status.runs to hylab_status;
grant select, insert, update on hylab_status.incidents to hylab_status;
grant usage, select on all sequences in schema hylab_status to hylab_status;

Without DATABASE_URL the app falls back to a local file (.data/uptime.json) so the page still works in development.

Import an existing local history into the database:

node scripts/migrate-uptime-to-db.cjs

Contributing

Contributions welcome — open an issue or PR.

git checkout -b feat/my-feature
npm run build  # must pass

License

MIT — free for personal and commercial use.


HyLab

HyLab — The Icons API for Modern Apps
26,150 icons from 11 families · One endpoint, any color, size, or format. Free and open source.



GitHub Status

Explore

Browse Icons
Documentation
About
System Status

Resources

GitHub
MIT License
No tracking · No cookies



© 2026 HyLab · Icons from Tabler, SF Symbols, Lucide & others — respective licenses apply. · Built by onyxax

About

HyLab — The Icons API for modern apps. 18,000+ icons from 10 sources (Tabler, Lucide, Heroicons, Phosphor, Remix, Carbon, Iconoir, BoxIcons, CSS.gg, Octicons). Fully customizable via URL: change color, size, stroke, and format (SVG/PNG/WebP). Free, open source, no auth required. Drop a URL into any project and get beautiful icons instantly.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages