TypeScript SDK for the Quikturn Logos API -- fetch any company's logo by domain name.
Get your API key -- free tier available, no credit card required.
| Package | Description | Install |
|---|---|---|
@quikturn/logos |
Core SDK -- URL builder, browser client, server client, web component | pnpm add @quikturn/logos |
@quikturn/logos-react |
React components -- logo, carousel, grid | pnpm add @quikturn/logos-react |
@quikturn/logos-next |
Next.js -- next/image wrapper, loaders, server helpers |
pnpm add @quikturn/logos-next |
@quikturn/logos-vue |
Vue 3 components -- logo, carousel, grid, plugin | pnpm add @quikturn/logos-vue |
@quikturn/logos-svelte |
Svelte 5 components -- logo, carousel, grid, runes | pnpm add @quikturn/logos-svelte |
@quikturn/logos-angular |
Angular 17+ -- standalone components, signals, pipe | pnpm add @quikturn/logos-angular |
pnpm add @quikturn/logosRequires Node.js >= 18. Works with pnpm, npm, or yarn.
Need an API key? Sign up at getquikturn.io -- takes 30 seconds.
| Entry Point | Import | Use Case |
|---|---|---|
| Universal | @quikturn/logos |
URL builder, types, constants -- zero dependencies, any runtime |
| Browser | @quikturn/logos/client |
Blob URLs, retry/backoff, scrape polling, events |
| Server | @quikturn/logos/server |
Buffer output, streaming, batch operations |
| Element | @quikturn/logos/element |
<quikturn-logo> web component with built-in attribution |
| Package | Import | Framework |
|---|---|---|
| React | @quikturn/logos-react |
React 18+ -- components, hooks, context |
| Next.js | @quikturn/logos-next |
Next.js 14+ -- next/image wrapper, server helpers |
| Vue | @quikturn/logos-vue |
Vue 3.3+ -- SFCs, composables, plugin |
| Svelte | @quikturn/logos-svelte |
Svelte 5 -- runes, snippets, context |
| Angular | @quikturn/logos-angular |
Angular 17+ -- standalone components, signals, pipe |
The simplest way to get a logo URL. Runs everywhere -- browsers, Node.js, edge runtimes -- with no network calls.
import { logoUrl } from "@quikturn/logos";
const url = logoUrl("github.com");
// => "https://logos.getquikturn.io/github.com"
const url = logoUrl("stripe.com", {
token: "qt_abc123",
size: 256,
format: "webp",
greyscale: true,
theme: "dark",
});import { QuikturnLogos } from "@quikturn/logos/client";
const client = new QuikturnLogos({ token: "qt_your_publishable_key" });
const { url, blob, contentType } = await client.get("github.com", {
size: 256,
format: "webp",
});
document.querySelector("img")!.src = url;
// Clean up blob URLs when done
client.destroy();import { QuikturnLogos } from "@quikturn/logos/server";
const client = new QuikturnLogos({ secretKey: "sk_your_secret_key" });
// Single logo
const { buffer, contentType } = await client.get("github.com");
// Batch fetch
for await (const result of client.getMany(["github.com", "stripe.com", "vercel.com"])) {
if (result.success) console.log(`${result.domain}: ${result.buffer!.byteLength} bytes`);
}
// Stream to file
import { createWriteStream } from "node:fs";
import { Readable } from "node:stream";
const stream = await client.getStream("github.com", { format: "png" });
Readable.fromWeb(stream).pipe(createWriteStream("logo.png"));No framework needed. Import the element entry and use it in plain HTML:
<script type="module">
import "@quikturn/logos/element";
</script>
<quikturn-logo domain="github.com" token="qt_abc123" size="64"></quikturn-logo>Renders the logo with a "Powered by Quikturn" attribution badge protected by shadow DOM.
pnpm add @quikturn/logos-reactimport { QuikturnProvider, QuikturnLogo, QuikturnLogoCarousel } from "@quikturn/logos-react";
function App() {
return (
<QuikturnProvider token="qt_your_key">
<QuikturnLogo domain="github.com" size={64} />
<QuikturnLogoCarousel
domains={["github.com", "stripe.com", "vercel.com", "figma.com"]}
speed={120}
fadeOut
pauseOnHover
/>
</QuikturnProvider>
);
}Full API reference: @quikturn/logos-react docs
pnpm add @quikturn/logos-nextimport { QuikturnProvider, QuikturnImage } from "@quikturn/logos-next";
export default function Page() {
return (
<QuikturnProvider token="qt_your_key">
<QuikturnImage domain="github.com" width={128} height={128} alt="GitHub" />
</QuikturnProvider>
);
}Full API reference: @quikturn/logos-next docs
pnpm add @quikturn/logos-vue<script setup lang="ts">
import { QuikturnLogo, QuikturnLogoCarousel } from "@quikturn/logos-vue";
</script>
<template>
<QuikturnLogo domain="github.com" :size="64" />
<QuikturnLogoCarousel
:domains="['github.com', 'stripe.com', 'vercel.com', 'figma.com']"
:speed="120"
fade-out
pause-on-hover
/>
</template>Full API reference: @quikturn/logos-vue docs
pnpm add @quikturn/logos-svelte<script>
import { QuikturnProvider, QuikturnLogo, QuikturnLogoCarousel } from "@quikturn/logos-svelte";
</script>
<QuikturnProvider token="qt_your_key">
<QuikturnLogo domain="github.com" size={64} />
<QuikturnLogoCarousel
domains={["github.com", "stripe.com", "vercel.com", "figma.com"]}
speed={120}
fadeOut
pauseOnHover
/>
</QuikturnProvider>Full API reference: @quikturn/logos-svelte docs
pnpm add @quikturn/logos-angular// app.config.ts
import { provideQuikturnLogos } from "@quikturn/logos-angular";
export const appConfig = {
providers: [provideQuikturnLogos({ token: "qt_your_key" })],
};import { Component } from "@angular/core";
import { QuikturnLogoComponent, QuikturnLogoCarouselComponent } from "@quikturn/logos-angular";
@Component({
selector: "app-example",
standalone: true,
imports: [QuikturnLogoComponent, QuikturnLogoCarouselComponent],
template: `
<quikturn-logo domain="github.com" [size]="64" />
<quikturn-logo-carousel
[domains]="['github.com', 'stripe.com', 'vercel.com', 'figma.com']"
[speed]="120"
[fadeOut]="true"
[pauseOnHover]="true"
/>
`,
})
export class ExampleComponent {}Full API reference: @quikturn/logos-angular docs
| Key Type | Prefix | Environment | Auth Method |
|---|---|---|---|
| Publishable | qt_ / pk_ |
Browser | Query parameter (?token=...) |
| Secret | sk_ |
Server only | Authorization: Bearer header |
Publishable keys are safe to expose in client-side code (max 800px). Secret keys must never reach the browser (max 1200px). Manage your keys in the Quikturn dashboard.
// Browser
import { QuikturnLogos } from "@quikturn/logos/client";
const client = new QuikturnLogos({ token: "qt_your_publishable_key" });
// Server
import { QuikturnLogos } from "@quikturn/logos/server";
const client = new QuikturnLogos({ secretKey: "sk_your_secret_key" });Pure URL builder. No network calls, no side effects.
import { logoUrl } from "@quikturn/logos";Options:
| Property | Type | Default | Description |
|---|---|---|---|
token |
string |
-- | API key appended as query parameter |
size |
number |
128 |
Output width in pixels |
width |
number |
128 |
Alias for size |
greyscale |
boolean |
false |
Desaturation filter |
theme |
"light" | "dark" |
-- | Background-optimized rendering |
format |
string |
"image/png" |
"png", "jpeg", "webp", "avif" (or full MIME type) |
Returns: string | Throws: DomainValidationError
import { QuikturnLogos } from "@quikturn/logos/client";| Option | Type | Default | Description |
|---|---|---|---|
token |
string |
required | Publishable key (qt_/pk_ prefix) |
| maxRetries | number | 2 | Max retries for 429/5xx responses |
client.get(domain, options?) -- Fetches a logo and returns a blob URL.
| Option | Type | Default |
|---|---|---|
size |
number |
128 |
format |
string |
"image/png" |
greyscale |
boolean |
false |
theme |
"light" | "dark" |
-- |
scrapeTimeout |
number |
-- |
onScrapeProgress |
(event) => void |
-- |
signal |
AbortSignal |
-- |
Returns Promise<{ url: string, blob: Blob, contentType: string, metadata: LogoMetadata }>.
client.getUrl(domain, options?) -- Returns a plain URL string without a network request.
client.on(event, handler) / client.off(event, handler) -- Listen for "rateLimitWarning" or "quotaWarning" events.
client.destroy() -- Revokes all tracked blob URLs and removes event listeners. Call this to prevent memory leaks.
import { QuikturnLogos } from "@quikturn/logos/server";| Option | Type | Default | Description |
|---|---|---|---|
secretKey |
string |
required | Secret key (sk_ prefix) |
| maxRetries | number | 2 | Max retries for 429/5xx responses |
client.get(domain, options?) -- Returns Promise<{ buffer: Buffer, contentType: string, metadata: LogoMetadata }>.
client.getMany(domains, options?) -- Batch fetch with concurrency control. Returns AsyncGenerator<BatchResult>.
| Option | Type | Default |
|---|---|---|
concurrency |
number |
5 |
continueOnError |
boolean |
true |
signal |
AbortSignal |
-- |
client.getStream(domain, options?) -- Returns Promise<ReadableStream> for zero-copy streaming.
client.getUrl(domain, options?) -- Returns a URL string (secret key NOT included -- use Authorization header).
client.on(event, handler) / client.off(event, handler) -- Same events as the browser client.
import "@quikturn/logos/element";| Attribute | Type | Description |
|---|---|---|
domain |
string |
Domain to fetch logo for (required) |
token |
string |
Publishable API key |
size |
string |
Image width in pixels |
format |
string |
"png", "jpeg", "webp", or "avif" |
greyscale |
(presence) | Greyscale filter when attribute is present |
theme |
string |
"light" or "dark" |
Auto-registers as <quikturn-logo> on import. Shadow DOM protects the attribution badge with !important CSS rules.
All errors extend LogoError with a typed code property for exhaustive switch handling:
import { LogoError } from "@quikturn/logos";
try {
const { url } = await client.get("example.com");
} catch (err) {
if (err instanceof LogoError) {
switch (err.code) {
case "RATE_LIMIT_ERROR": /* backoff */ break;
case "NOT_FOUND_ERROR": /* fallback */ break;
case "AUTHENTICATION_ERROR": /* check key */ break;
// ...
}
}
}| Error | Code | Status | Extra Properties |
|---|---|---|---|
DomainValidationError |
DOMAIN_VALIDATION_ERROR |
-- | domain |
AuthenticationError |
AUTHENTICATION_ERROR |
401 | -- |
ForbiddenError |
FORBIDDEN_ERROR |
403 | reason |
NotFoundError |
NOT_FOUND_ERROR |
404 | domain |
BadRequestError |
BAD_REQUEST_ERROR |
400 | -- |
RateLimitError |
RATE_LIMIT_ERROR |
429 | retryAfter, remaining, resetAt |
QuotaExceededError |
QUOTA_EXCEEDED_ERROR |
429 | retryAfter, limit, used |
ScrapeTimeoutError |
SCRAPE_TIMEOUT_ERROR |
-- | jobId, elapsed |
import type {
ThemeOption, // "light" | "dark"
SupportedOutputFormat, // "image/png" | "image/jpeg" | "image/webp" | "image/avif"
FormatShorthand, // "png" | "jpeg" | "webp" | "avif"
LogoRequestOptions,
LogoMetadata,
BrowserLogoResponse,
ServerLogoResponse,
ScrapeProgressEvent,
LogoErrorCode, // discriminated union of all error codes
} from "@quikturn/logos";| Constant | Value |
|---|---|
BASE_URL |
"https://logos.getquikturn.io" |
DEFAULT_WIDTH |
128 |
DEFAULT_FORMAT |
"image/png" |
SUPPORTED_FORMATS |
Set of 4 MIME types |
FORMAT_ALIASES |
{ png, jpeg, webp, avif } -> MIME mapping |
| Format | Shorthand | MIME Type |
|---|---|---|
| PNG | "png" |
image/png |
| JPEG | "jpeg" |
image/jpeg |
| WebP | "webp" |
image/webp |
| AVIF | "avif" |
image/avif |
Both forms are accepted: format: "webp" and format: "image/webp" are equivalent.
Use "light" for light backgrounds and "dark" for dark backgrounds. The API adjusts the logo's color profile to maximize contrast.
Rate limits and monthly quotas are enforced server-side and vary by plan. The SDK automatically retries with exponential backoff when limits are hit and emits "rateLimitWarning" / "quotaWarning" events so you can react in your UI. See pricing & plan details.
- Quikturn website -- sign up, manage keys, explore the API
- Dashboard -- usage analytics, key management, plan upgrades
- Pricing -- free tier, pro, and enterprise plans
- React components --
@quikturn/logos-reactdocs - Next.js components --
@quikturn/logos-nextdocs - Vue components --
@quikturn/logos-vuedocs - Svelte components --
@quikturn/logos-sveltedocs - Angular components --
@quikturn/logos-angulardocs - GitHub -- source, issues, contributions
We welcome, appreciate, and applaud all contributions! See CONTRIBUTING.md for setup instructions and guidelines.
MIT -- built by Quikturn