TL;DR
Scalar is the modern API documentation UI — beautiful design, built-in API client for testing, dark mode, OpenAPI 3.1 support, customizable theming. Redoc is the three-panel API docs renderer — clean three-column layout, OpenAPI 3.x, search, code samples, used by major API providers. Swagger UI is the original OpenAPI renderer — interactive "Try it out" feature, the most widely used, powers SwaggerHub, official OpenAPI tooling. In 2026: Scalar for modern beautiful docs with API client, Redoc for clean reference documentation, Swagger UI for interactive API testing.
Key Takeaways
- Scalar: ~500K weekly downloads — modern UI, API client, dark mode, OpenAPI 3.1
- Redoc: ~1M weekly downloads — three-panel layout, search, code samples
- Swagger UI: ~3M weekly downloads — "Try it out", most widely used, official tooling
- All three render OpenAPI/Swagger specs into interactive documentation
- Scalar has the most modern design and built-in API testing
- Swagger UI's "Try it out" makes live API requests from the docs
Scalar
Scalar — modern API documentation:
Basic setup
<!-- CDN (quickest start): -->
<script
id="api-reference"
data-url="https://api.pkgpulse.com/openapi.json"
></script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
Express integration
import express from "express"
import { apiReference } from "@scalar/express-api-reference"
const app = express()
app.use(
"/docs",
apiReference({
spec: {
url: "/openapi.json",
},
theme: "purple",
})
)
app.get("/openapi.json", (req, res) => {
res.json(openapiSpec)
})
// → http://localhost:3000/docs
Hono integration
import { Hono } from "hono"
import { apiReference } from "@scalar/hono-api-reference"
const app = new Hono()
app.get(
"/docs",
apiReference({
spec: { url: "/openapi.json" },
pageTitle: "PkgPulse API",
theme: "kepler",
})
)
Configuration
import { apiReference } from "@scalar/express-api-reference"
app.use("/docs", apiReference({
spec: { url: "/openapi.json" },
// Theme:
theme: "purple", // purple, saturn, kepler, mars, moon, default
darkMode: true,
// Customization:
layout: "modern", // modern, classic
showSidebar: true,
// Authentication:
authentication: {
preferredSecurityScheme: "bearerAuth",
apiKey: {
token: "default-api-key",
},
},
// Custom CSS:
customCss: `
.scalar-app { --scalar-color-1: #3b82f6; }
`,
// Metadata:
metaData: {
title: "PkgPulse API Reference",
description: "Compare npm packages",
},
}))
Features
Scalar highlights:
✅ Built-in API client (test endpoints without leaving docs)
✅ Dark mode (toggleable)
✅ Modern, clean design
✅ OpenAPI 3.0 and 3.1 support
✅ Search across endpoints
✅ Request/response examples
✅ Multiple language code samples
✅ Authentication support
✅ Customizable themes
✅ Framework integrations (Express, Hono, Fastify, Next.js)
Redoc
Redoc — three-panel docs:
Basic setup
<!-- CDN: -->
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
<div id="redoc-container"></div>
<script>
Redoc.init("https://api.pkgpulse.com/openapi.json", {
theme: {
colors: { primary: { main: "#3b82f6" } },
},
}, document.getElementById("redoc-container"))
</script>
React component
import { RedocStandalone } from "redoc"
function APIReference() {
return (
<RedocStandalone
specUrl="https://api.pkgpulse.com/openapi.json"
options={{
theme: {
colors: {
primary: { main: "#3b82f6" },
},
typography: {
fontFamily: "Inter, sans-serif",
},
sidebar: {
backgroundColor: "#1a1a1a",
textColor: "#ffffff",
},
},
hideDownloadButton: false,
expandResponses: "200,201",
requiredPropsFirst: true,
sortPropsAlphabetically: true,
pathInMiddlePanel: true,
}}
/>
)
}
Express middleware
import express from "express"
import redoc from "redoc-express"
const app = express()
app.get("/docs", redoc({
title: "PkgPulse API",
specUrl: "/openapi.json",
redocOptions: {
theme: {
colors: { primary: { main: "#3b82f6" } },
},
},
}))
Configuration
const redocOptions = {
// Layout:
hideDownloadButton: false,
hideHostname: false,
hideLoading: false,
hideSchemaPattern: false,
hideSingleRequestSampleTab: false,
// Content:
expandResponses: "200,201", // Auto-expand these status codes
requiredPropsFirst: true,
sortPropsAlphabetically: true,
pathInMiddlePanel: true,
jsonSampleExpandLevel: 2,
// Sidebar:
menuToggle: true,
nativeScrollbars: false,
// Code samples:
generateCodeSamples: {
languages: [
{ lang: "curl" },
{ lang: "Node.js" },
{ lang: "Python" },
],
},
// Theme:
theme: {
colors: {
primary: { main: "#3b82f6" },
success: { main: "#10b981" },
error: { main: "#ef4444" },
},
typography: {
fontFamily: "Inter, sans-serif",
fontSize: "15px",
headings: { fontFamily: "Inter, sans-serif" },
},
sidebar: {
width: "260px",
backgroundColor: "#1a1a1a",
},
rightPanel: {
backgroundColor: "#0f172a",
},
},
}
Swagger UI
Swagger UI — interactive API docs:
Basic setup
<!-- CDN: -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist/swagger-ui.css" />
<div id="swagger-ui"></div>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist/swagger-ui-bundle.js"></script>
<script>
SwaggerUIBundle({
url: "https://api.pkgpulse.com/openapi.json",
dom_id: "#swagger-ui",
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset,
],
})
</script>
Express integration
import express from "express"
import swaggerUi from "swagger-ui-express"
import openapiSpec from "./openapi.json"
const app = express()
app.use("/docs", swaggerUi.serve, swaggerUi.setup(openapiSpec, {
customSiteTitle: "PkgPulse API",
customCss: ".swagger-ui .topbar { display: none }",
swaggerOptions: {
persistAuthorization: true,
displayRequestDuration: true,
filter: true,
tryItOutEnabled: true,
},
}))
// → http://localhost:3000/docs
"Try it out" feature
Swagger UI's killer feature — execute API requests from the docs:
1. Open endpoint: GET /api/packages
2. Click "Try it out"
3. Fill in parameters: name = "react"
4. Click "Execute"
5. See real response:
curl -X GET "https://api.pkgpulse.com/api/packages?name=react"
Response:
200 OK
{
"name": "react",
"downloads": 25000000,
"version": "19.0.0"
}
This makes API testing and exploration interactive.
Configuration
import swaggerUi from "swagger-ui-express"
const options = {
// UI options:
customSiteTitle: "PkgPulse API",
customfavIcon: "/favicon.ico",
customCss: `
.swagger-ui .topbar { display: none }
.swagger-ui .info .title { color: #3b82f6 }
`,
// Swagger options:
swaggerOptions: {
persistAuthorization: true,
displayRequestDuration: true,
docExpansion: "list", // "list", "full", "none"
filter: true, // Search filter
tryItOutEnabled: true, // Enable "Try it out" by default
defaultModelsExpandDepth: 2,
defaultModelExpandDepth: 2,
// OAuth2:
oauth2RedirectUrl: "https://api.pkgpulse.com/docs/oauth2-redirect",
initOAuth: {
clientId: "your-client-id",
scopes: ["read", "write"],
},
},
}
app.use("/docs", swaggerUi.serve, swaggerUi.setup(spec, options))
Feature Comparison
| Feature | Scalar | Redoc | Swagger UI |
|---|---|---|---|
| Design | Modern, beautiful | Three-panel | Classic |
| Dark mode | ✅ (built-in) | ✅ (theme) | ❌ (custom CSS) |
| "Try it out" | ✅ (API client) | ❌ (paid addon) | ✅ |
| Search | ✅ | ✅ | ✅ (filter) |
| Code samples | ✅ | ✅ | ❌ |
| OpenAPI 3.1 | ✅ | ✅ | ✅ |
| OpenAPI 3.0 | ✅ | ✅ | ✅ |
| Swagger 2.0 | ❌ | ✅ | ✅ |
| React component | ✅ | ✅ | ✅ |
| Express middleware | ✅ | ✅ | ✅ |
| Hono/Fastify | ✅ | ❌ | ✅ (Fastify) |
| Custom theming | ✅ | ✅ (deep) | ✅ (CSS) |
| Self-hosted | ✅ | ✅ | ✅ |
| Weekly downloads | ~500K | ~1M | ~3M |
When to Use Each
Use Scalar if:
- Want the most modern, beautiful API documentation
- Need a built-in API client for testing endpoints
- Building with Hono, Express, or Fastify
- Want dark mode and customizable themes out of the box
Use Redoc if:
- Need clean three-panel reference documentation
- Want auto-generated code samples in multiple languages
- Building public-facing API docs for developer portals
- Need deep theming and branding customization
Use Swagger UI if:
- Need interactive "Try it out" API testing
- Want the most widely recognized API docs format
- Need OAuth2 flow support in the docs
- Have Swagger 2.0 specs (legacy support)
Methodology
Download data from npm registry (weekly average, February 2026). Feature comparison based on @scalar/api-reference v1.x, redoc v2.x, and swagger-ui-express v5.x.
OpenAPI Spec Quality and Documentation Completeness
The quality of your API documentation output depends as much on your OpenAPI specification as it does on which renderer you choose. All three tools render what they're given — a sparse OpenAPI spec with minimal descriptions and no examples will produce poor documentation regardless of whether Scalar, Redoc, or Swagger UI renders it.
Redoc incentivizes rich specifications more than the other two because of how it uses OpenAPI extension fields. The x-logo extension adds branding, x-tagGroups organizes endpoints into nested sidebar groups (essential for APIs with more than ~20 endpoints), and inline Markdown in description fields renders beautifully in Redoc's three-panel layout. For teams building developer portals for external APIs — where documentation is part of the product — Redoc's rendering of richly annotated specs is consistently the most polished.
Scalar's API client requires accurate request/response schemas in the spec to be useful for testing. If your OpenAPI spec omits requestBody schemas or example values, testers have no guidance on what to send. Scalar shines when used alongside tools like @hono/zod-openapi or fastify-swagger that generate the spec programmatically from route definitions — these generate complete, accurate schemas automatically, giving Scalar's client full information to work with.
Swagger UI's "Try it out" feature is most useful when your API has straightforward authentication. If the spec includes a securitySchemes definition for Bearer auth or API keys, Swagger UI's "Authorize" button lets developers enter their credentials once and all subsequent "Try it out" requests include them automatically. For internal developer tools where the API is behind an auth gateway, this workflow is genuinely useful for API exploration.
Self-Hosting vs. Managed Documentation Services
All three libraries support self-hosted deployment, but they differ meaningfully in what that requires and what alternatives exist. Self-hosting any of these tools is straightforward: serve the HTML/JS bundle from your backend as shown in the integration examples above. The main operational consideration is keeping the documentation URL behind your existing auth if the API is private — none of the three has built-in auth on the documentation page itself.
Redocly (the company behind Redoc) offers managed documentation hosting with additional features: versioned documentation, custom domains, team access controls, and analytics on which endpoints developers look at most. The managed tier is significant for companies where documentation quality is a product differentiator (SDKs, public APIs, developer platforms). The open-source Redoc library is free, but the Redocly platform is paid.
Scalar also offers a hosted platform with similar capabilities, including a CLI tool (scalar mock) for generating a local mock server from your OpenAPI spec — useful for frontend development when the real API isn't available. The hosted Scalar platform has a free tier that makes it easy to publish docs from a public OpenAPI spec URL without any infrastructure.
For greenfield projects in 2026, the recommended starting point is Scalar served directly from your API framework (Hono, Express, or Fastify all have official Scalar middleware packages). You get modern documentation with API testing out of the box in under 10 minutes of setup, and you can migrate to a hosted platform later if you need versioning or team features.
Generating OpenAPI Specs from Code
The choice of documentation renderer becomes secondary to the approach for generating your OpenAPI spec. Manually maintaining an OpenAPI YAML/JSON file alongside your API code is error-prone — the spec drifts from the implementation, and developers stop updating it. Code-first spec generation is more maintainable.
For Hono, @hono/zod-openapi extends Zod schemas with OpenAPI metadata and registers them as route definitions that automatically produce a /openapi.json endpoint. Each route's input validation schema and output type are defined once and serve dual purpose: runtime validation and spec generation. For Fastify, @fastify/swagger with fastify-type-provider-zod achieves the same result. For NestJS applications, the @nestjs/swagger decorator-based approach generates specs from TypeScript decorators on controller methods.
Scalar's and Redoc's framework integrations are designed to point at this generated spec URL rather than a static file — the documentation stays in sync with the code automatically.
Compare API tooling and documentation libraries on PkgPulse →
Authentication Flows and Developer Portal Considerations
One dimension that meaningfully differentiates these tools for production use is how they handle authentication during the "try it out" experience. Swagger UI's OAuth 2.0 support is the most comprehensive of the three — the built-in "Authorize" dialog walks developers through OAuth authorization code flows, accepting client credentials and storing tokens in the UI session. For APIs using OAuth 2.0 (most enterprise APIs), this built-in flow lets developers authenticate without leaving the documentation page, reducing the friction of the "get a token, then test" workflow.
Scalar's API client supports authentication but approaches it differently: you configure authentication schemes in the spec's securitySchemes section, and Scalar's client UI presents fields for the required credentials (API key, bearer token, basic auth) at the top of the interface. The experience is streamlined for simpler auth patterns but lacks OAuth 2.0's full authorization flow by default. For internal APIs using API keys or pre-obtained bearer tokens, Scalar's approach is more than sufficient and its default authentication configuration options cover the common cases cleanly.
Redoc's open-source version does not have a built-in "try it out" feature at all — authentication configuration in Redoc's free tier only affects how the documentation displays auth requirements, not interactive testing. The Redocly paid platform adds a try-it-out console with auth support. For developer portals where interactive testing is a requirement, this means Redoc requires either the paid platform or embedding a separate tool (like a Postman button or a custom API client) alongside the documentation.
For teams building developer portals as a product — where the documentation is part of the API's value proposition rather than just internal tooling — Scalar's modern design and Redoc's depth of customization are both appropriate choices depending on the complexity of the API and the maturity of the design system requirements. Swagger UI's classic appearance can feel dated for external developer portals, though its "try it out" workflow remains unmatched for rapid API exploration.
In 2026, Scalar is the rising choice for teams that want modern, beautiful API documentation with a premium feel — it is actively developed and has the best developer experience of the three. Redoc is the proven choice for large, complex APIs where long-form documentation and deep customization are requirements. Swagger UI remains the most familiar tool for developers already in the OpenAPI ecosystem — its interactive "try it out" feature is still the fastest way to let consumers test API endpoints without leaving the browser. All three read the same OpenAPI YAML/JSON spec, so the choice is purely about presentation and hosting preferences.
See also: AVA vs Jest and dinero.js vs currency.js vs Intl.NumberFormat, change-case vs camelcase vs slugify.