SVGL, an SVG logo library with a free API
SVGL is a catalogue of brand marks in SVG format, collected in one place and available both from the site and through an open API requiring no key. At the time of writing the catalogue holds 665 entries across 41 categories. The project's code is MIT licensed, the logos themselves are not, and that distinction is the most important thing here.
The problem it solves
A situation familiar to anyone who has assembled a technology section on a page: you need twelve logos and each lives somewhere else. One turns up in the vendor's press kit, another only as a raster image in search results, a third in a repository but in a version predating a rebrand. The result is a section where half the marks are blurry and one dates from 2019.
SVGL collects them in a single catalogue, in a consistent format, with variants for light and dark backgrounds. The marks are vector, so they scale without quality loss and weigh little, and they can be recoloured through CSS, which a raster image will never allow.
This is convenience rather than a breakthrough, and it is fair to say so. You save an hour of work on one page. The value grows once you do it regularly: in documentation, in an agency building many sites, or in a tool directory where logos are a repeating element.
Trademark rights, the essential caveat
This is the section missing from most material about this project, and it carries real legal weight.
The MIT licence covers the site's code and the API. It does not cover the logos, because brand marks belong to the companies that registered them, and no collection sets them free. The project helps in part: some API entries carry a brandUrl field linking to the owner's usage rules. Only 158 of the 665 entries have it, though, so for the rest the rules have to be found on the vendor's own site.
Two practical consequences follow. Use in an informational context, showing which technologies your product runs on, or illustrating an article, generally falls within fair use of a mark. Use implying a relationship that does not exist is an entirely different matter: a "trusted by" section carrying logos of companies who are not your customers is a problem regardless of where you got the file.
The rule that organises the rest: you may show a mark to state a truth about a relationship, not to imply one. When in doubt, start with the brandUrl field in the API response, and where a mark does not carry one, look up the brand rules on the owner's site.
Modifications deserve separate attention. Changing proportions, adding an outline, or recolouring a mark to your own brand colour breaches most companies' rules, even when the SVG file technically permits it. The exception is a single colour variant, which many companies explicitly allow.
Access through the API
The interface is public and requires no key, which distinguishes it from most comparable catalogues.
curl https://api.svgl.appThe response is an array of entries carrying, alongside title and category, the file address and, on some entries, the address of the mark's usage rules:
{
"id": 0,
"title": "Plausible Analytics",
"category": "Analytics",
"route": "https://svgl.app/library/plausible.svg",
"brandUrl": "https://plausible.io/trademark",
"url": "https://plausible.io/"
}A variants field appears where a mark has separate versions for light and dark backgrounds, and then instead of a single address you receive an object holding two. Code reading this data has to handle both shapes, or it will break on the first mark with variants.
Approach this API with some restraint. It needs no key, but a request limit already applies, and the documentation explicitly asks you to cache responses on your side rather than fetching the same data on every call. Querying it on every page render is therefore both an abuse and a poor technical idea, since it ties your site to somebody else's availability. Download the files you need once and keep them yourself, treating the API as a tool for assembling that set rather than as a runtime source.
Project status
The pheralb/svgl repository carries over six thousand stars, an MIT licence, and is written in TypeScript on SvelteKit. The most recent changes date from July 2026, so the project is maintained.
It is worth understanding how catalogues like this work, though. A small group usually develops them, and new marks arrive through community submissions. That means currency is uneven: popular technologies carry up to date marks, while lesser known ones can linger on a pre-rebrand logo. Before putting a mark on a client's site, glance at the vendor's own page and compare.
A practical point about dependency follows from that. A project maintained by a small group can change its API address, tighten its request limit, or simply slow down, and none of that would be anybody's fault. If you are building something meant to last years, treat the catalogue as a source for a one off download rather than as a piece of architecture. Files in your own repository will keep working whatever happens to the project, and refreshing them occasionally is a matter of one script.
Logo categories
Technologies and frameworks
| Category | Count | Examples |
|---|---|---|
| Framework | 52 | Vue, Angular, Astro, NestJS |
| Library | 77 | React, Svelte, Preact, Redux |
| Language | 36 | JavaScript, TypeScript, Python, Rust |
| Database | 23 | PostgreSQL, MongoDB, Redis |
| Compiler | 9 | Babel, esbuild, SWC, Rolldown |
Platforms and services
| Category | Count | Examples |
|---|---|---|
| 22 | Gmail, Google Cloud, Firebase | |
| Microsoft | 27 | Azure, VS Code, Teams |
| Vercel | 6 | Vercel, Next.js, Turborepo |
| Hosting | 15 | Netlify, Render, Fly |
| CMS | 13 | Strapi, Sanity, WordPress |
Other
| Category | Count | Examples |
|---|---|---|
| AI | 67 | OpenAI, Anthropic, Hugging Face |
| Design | 62 | Figma, Sketch, Adobe |
| Crypto | 22 | Bitcoin, Ethereum, Solana |
| Social | 28 | X (formerly Twitter), LinkedIn, Mastodon |
| Software | 283 | Slack, Notion, Zoom |
How to use SVGL
Method 1: Website (simplest)
- Visit svgl.app
- Search or browse categories
- Click on a logo
- Choose format (SVG, PNG, JSX)
- Copy or download
Method 2: API
// Get all logos
const response = await fetch('https://api.svgl.app')
const logos = await response.json()
// Search for a specific logo
const react = logos.find(logo => logo.title === 'React')
console.log(react.route) // URL to SVGAPI Response:
{
"id": 40,
"title": "React",
"category": "Library",
"route": {
"light": "https://svgl.app/library/react_light.svg",
"dark": "https://svgl.app/library/react_dark.svg"
},
"wordmark": {
"light": "https://svgl.app/library/react_wordmark_light.svg",
"dark": "https://svgl.app/library/react_wordmark_dark.svg"
},
"url": "https://react.dev/"
}Method 3: the shadcn/ui registry
Since version 5 SVGL ships its own shadcn/ui registry, so marks are added with the same command as components. First a one off entry in components.json:
{
"registries": {
"@svgl": "https://svgl.app/r/{name}.json"
}
}Then installing a single mark or several at once:
npx shadcn@latest add @svgl/sanity
pnpm dlx shadcn@latest add @svgl/sanity @svgl/github @svgl/supabase @svgl/vercelYou get a finished component inside your own project rather than a reference to somebody else's server, so the mark keeps working whatever happens to the catalogue. The same configuration backs the shadcn MCP server, if you prefer adding marks by instructing an assistant.
Method 4: Direct URL
<!-- Direct link to SVG -->
<img src="https://svgl.app/library/react_light.svg" alt="React" />
<!-- In markdown -->
Practical examples
Tech Stack Section
// components/TechStack.tsx
const technologies = [
{ name: "React", url: "https://svgl.app/library/react_light.svg" },
{ name: "Next.js", url: "https://svgl.app/library/nextjs_icon_dark.svg" },
{ name: "TypeScript", url: "https://svgl.app/library/typescript.svg" },
{ name: "Tailwind", url: "https://svgl.app/library/tailwindcss.svg" },
{ name: "Prisma", url: "https://svgl.app/library/prisma.svg" },
{ name: "Vercel", url: "https://svgl.app/library/vercel.svg" },
]
export function TechStack() {
return (
<section className="py-16">
<h2 className="text-2xl font-bold text-center mb-8">Tech Stack</h2>
<div className="flex flex-wrap justify-center gap-8">
{technologies.map((tech) => (
<div key={tech.name} className="flex flex-col items-center gap-2">
<img
src={tech.url}
alt={tech.name}
className="h-12 w-12 grayscale hover:grayscale-0 transition-all"
/>
<span className="text-sm text-gray-600">{tech.name}</span>
</div>
))}
</div>
</section>
)
}Logos Marquee
// components/LogosMarquee.tsx
import { motion } from "framer-motion"
const logos = [
"react_light", "vue", "angular", "svelte", "nextjs_icon_dark",
"nuxt", "astro-icon-light", "remix_light", "gatsby", "qwik"
]
export function LogosMarquee() {
return (
<div className="overflow-hidden py-8">
<motion.div
className="flex gap-12"
animate={{ x: [0, -1000] }}
transition={{
duration: 20,
repeat: Infinity,
ease: "linear"
}}
>
{[...logos, ...logos].map((logo, i) => (
<img
key={i}
src={`https://svgl.app/library/${logo}.svg`}
alt={logo}
className="h-8 w-auto opacity-50 hover:opacity-100 transition-opacity"
/>
))}
</motion.div>
</div>
)
}Trusted By Section
// components/TrustedBy.tsx
const companies = [
{ name: "Google", logo: "google" },
{ name: "Microsoft", logo: "microsoft" },
{ name: "Vercel", logo: "vercel" },
{ name: "Stripe", logo: "stripe" },
{ name: "GitHub", logo: "github_light" },
]
export function TrustedBy() {
return (
<section className="bg-gray-50 py-12">
<p className="text-center text-gray-500 mb-8">
Trusted by leading companies
</p>
<div className="flex justify-center items-center gap-12 flex-wrap">
{companies.map((company) => (
<img
key={company.name}
src={`https://svgl.app/library/${company.logo}.svg`}
alt={company.name}
className="h-8 opacity-60 grayscale"
/>
))}
</div>
</section>
)
}Documentation Page
// components/docs/TechBadge.tsx
interface TechBadgeProps {
name: string
version?: string
}
export function TechBadge({ name, version }: TechBadgeProps) {
return (
<div className="inline-flex items-center gap-2 px-3 py-1 bg-gray-100 rounded-full">
<img
src={`https://svgl.app/library/${name.toLowerCase()}.svg`}
alt={name}
className="h-4 w-4"
/>
<span className="text-sm font-medium">{name}</span>
{version && (
<span className="text-xs text-gray-500">{version}</span>
)}
</div>
)
}
// Usage in documentation
<TechBadge name="React" version="18.2" />
<TechBadge name="TypeScript" version="5.0" />API Reference
Endpoints
// All logos
GET https://api.svgl.app
// Categories
GET https://api.svgl.app/categories
// Logos by category
GET https://api.svgl.app/category/frameworkResponse Types
type ThemeOptions = {
light: string
dark: string
}
interface SVG {
id: number
title: string
category: string | string[] // one category or a list of them
route: string | ThemeOptions // one file, or a light and a dark variant
url: string // official website
wordmark?: string | ThemeOptions
brandUrl?: string // usage rules, present on some entries only
}Usage with fetch
// lib/svgl.ts
export async function getAllLogos() {
const res = await fetch('https://api.svgl.app')
return res.json()
}
export async function getLogosByCategory(category: string) {
const logos = await getAllLogos()
return logos.filter(logo =>
Array.isArray(logo.category)
? logo.category.includes(category)
: logo.category === category
)
}
export async function searchLogos(query: string) {
const logos = await getAllLogos()
return logos.filter(logo =>
logo.title.toLowerCase().includes(query.toLowerCase())
)
}Adding logos
If a logo is missing, you can add it:
- Fork the repository github.com/pheralb/svgl
- Add SVG to
/static/library/ - Update
/src/data/svgs.ts - Create a Pull Request
Logo requirements
- Format: SVG
- Size: Optimized (remove unnecessary attributes)
- Quality: Official logo or approved fanmade
- License: Check brand guidelines
Tips & tricks
Dark mode logos
Some logos have versions for dark backgrounds:
// Check if logo has dark variant
function LogoWithTheme({ name, theme }) {
const [logo, setLogo] = useState(null)
useEffect(() => {
fetch('https://api.svgl.app')
.then(res => res.json())
.then(logos => {
const found = logos.find(l => l.title.toLowerCase() === name.toLowerCase())
setLogo(found)
})
}, [name])
if (!logo) return null
const src = typeof logo.route === 'object'
? logo.route[theme]
: logo.route
return <img src={src} alt={name} />
}Preloading popular logos
// In document head
<link rel="preload" as="image" href="https://svgl.app/library/react_light.svg" />
<link rel="preload" as="image" href="https://svgl.app/library/nextjs_icon_dark.svg" />Local caching
// Download and cache locally
async function downloadLogo(name: string, outputDir: string) {
const response = await fetch(`https://svgl.app/library/${name}.svg`)
const svg = await response.text()
await fs.writeFile(`${outputDir}/${name}.svg`, svg)
}Embedding logos without slowing the page
Vector files are light, but how you embed them can undo that advantage, so three approaches are worth knowing along with when each fits.
Inlining the file's contents directly in the page markup gives the most: the mark can be recoloured through CSS, responds to the theme, and generates no separate network request. The cost is document size, since each mark is a few hundred bytes of markup inside the page. For twelve logos in a technology section, that is the right choice.
Referencing the file through an image tag is simpler and keeps the markup clean, but each mark becomes a separate request and CSS recolouring stops working. With more marks scattered across a page this variant fares better, particularly in Next.js, where the image component handles the rest.
The third approach, most often overlooked, gathers the marks into one file of symbols referenced by identifier. A single request then serves every mark, and each remains recolourable. In a tool directory carrying a hundred logos the difference is clear.
Whichever variant you pick, run the files through an optimiser, which in a React project reduces to a single build step. Marks exported from graphics applications carry metadata, hidden layers, and excessive coordinate precision, so they can weigh several times more than they should. That applies to files from this catalogue too, since they originate in vendor press kits.
What this is not, and what to reach for instead
Setting expectations is worth doing, because this catalogue gets confused with two other categories of tool.
It is not an interface icon set. Brand marks and icons are different things: the first belong to specific companies and have a fixed shape, the second are functional elements designed as a coherent family and recoloured freely. For arrows, carts, and menu icons you want an icon set rather than a mark catalogue.
Nor is it a component library. You receive files, not finished sections carrying client logos or scrolling technology strips. The layout and animation are yours to assemble, or you take a ready section from a collection like TailGrids and drop these marks into it.
You will also not find marks from outside the technology world. The catalogue grew around developer tools and cloud services, so a bank's, a retailer's, or a car manufacturer's logo has to come from that company's own press materials.
One last matter concerns individual file quality. The marks come from vendor press kits and community submissions, so they vary: one has clean paths, another retains live text layers that will render wrong in a browser lacking the typeface. For marks central to your page, open the file and check whether text was converted to shapes.
Common mistakes
The first is querying the API on every page view. The catalogue is free and maintained by one person, so that traffic is an abuse, and your site becomes dependent on somebody else's uptime. Download the files once and keep them yourself.
The second is ignoring the dark background variant. Black marks vanish on a dark theme, and many carry a separate version for exactly that case. Checking both themes takes a moment and catches a problem users will not report, they will simply not see it.
The third is assuming a uniform API response shape. Some entries carry a single file address, others an object with two variants, so code always reading the same field will break on the first mark with variants.
The fourth is modifying marks. Changing proportions, adding a shadow, or recolouring to your own brand breaches most companies' rules. If a mark does not fit the layout, change the layout rather than the mark.
The fifth and most serious is using marks in a way that implies a relationship which does not exist. A section carrying logos of companies who are neither customers nor partners is a legal problem rather than a matter of taste, and no file licence changes that.
FAQ
Can I use these logos commercially?
The project's code is MIT licensed, the marks themselves are not. Each remains the property of the company that registered it and is governed by that company's rules. Some API entries carry a brandUrl field linking to those rules, but fewer than a quarter do, so for the rest you have to visit the owner's site.
How many logos does the catalogue hold?
At the time of writing 665 entries across 41 categories, with the number growing through community submissions. The current figure comes straight from the API, since it returns the whole list.
Does the API need a key?
No, it is public and free. That is precisely why it deserves restrained use: for assembling your own set of files rather than as a source queried on every user request.
Can I host the files myself?
Yes, and that is the recommended approach. Pulling files into your repository removes the dependency on someone else's infrastructure and lets you optimise them before deployment.
How do I add a missing logo?
Through a change proposal in the project repository: you add the file, fill in the data entry, and submit it. Contribution rules are documented in the repository itself.
The project code and submission rules live in the SVGL repository, and the full catalogue is on the project site.