Scalar API Documentation - Modern Alternative to Swagger UI for .NET
TL;DR: Scalar is the modern, beautiful API documentation UI that Microsoft now recommends over Swagger UI starting with .NET 9. This guide covers everything you need to know: implementation, CSP fixes, advanced customization, and migration from Swagger UI.
Introduction
With the release of .NET 9, Microsoft has made a significant change to how Web API documentation is generated by default. Instead of Swagger UI, which has been the de facto standard for years, .NET 9 projects now use Scalar - a modern, sleek alternative built for today's API development workflows.
If you're still using Swagger UI or wondering whether to make the switch, this comprehensive guide will walk you through:
- Why Microsoft chose Scalar over Swagger UI
- Step-by-step implementation in .NET 9 and earlier versions
- Solving common Content Security Policy (CSP) issues
- Advanced customization options
- Migration strategies from Swagger UI
What is Scalar?
Scalar is an open-source API documentation tool that generates beautiful, interactive documentation from your OpenAPI/Swagger specifications. Think of it as Swagger UI's modern successor - faster, more intuitive, and visually stunning.
Key Features
- Modern UI: Clean, responsive design with dark mode support
- Better Performance: Faster load times and rendering compared to Swagger UI
- Improved DX: More intuitive interface for developers testing APIs
- Smart Request Builder: Auto-generates request examples with proper syntax highlighting
- Advanced Searching: Full-text search across all endpoints and schemas
- OpenAPI 3.1 Support: Full compatibility with the latest OpenAPI specification
- Customizable Theming: Extensive branding and styling options
Scalar vs Swagger UI: The Comparison
Visual & User Experience
| Feature | Scalar | Swagger UI |
|---|---|---|
| UI Design | Modern, clean, visually appealing | Functional but dated |
| Dark Mode | Built-in, seamless switching | Limited or requires customization |
| Response Visualization | Syntax-highlighted, collapsible JSON/XML | Basic text display |
| Mobile Experience | Fully responsive, touch-optimized | Functional but not optimized |
| Load Time | Fast (~500ms average) | Slower (~1.5s average) |
Developer Experience
| Feature | Scalar | Swagger UI |
|---|---|---|
| Code Examples | Multiple languages (cURL, JavaScript, Python, C#, etc.) | Limited to cURL by default |
| Search Functionality | Full-text search across endpoints, parameters, schemas | Basic endpoint filtering |
| Request History | Built-in request history and favorites | Not available |
| Authentication Testing | Persistent auth tokens, OAuth2 flow support | Basic auth support, tokens don't persist |
| Response Schema View | Interactive, expandable schema explorer | Static schema display |
Technical Comparison
| Aspect | Scalar | Swagger UI |
|---|---|---|
| OpenAPI Support | OpenAPI 3.0, 3.1 (full support) | OpenAPI 2.0, 3.0 (limited 3.1) |
| Bundle Size | ~200KB gzipped | ~400KB gzipped |
| Framework Agnostic | Yes (works with any backend) | Yes (works with any backend) |
| CSP Compatibility | Requires unsafe-inline and unsafe-eval |
Requires unsafe-inline |
| Customization | Extensive theming, CSS variables, plugins | Limited to CSS overrides |
Microsoft's Stance: Why Scalar in .NET 9?
Starting with .NET 9, Microsoft has made Scalar the default API documentation UI for new Web API projects. Here's why:
"We believe Scalar represents the future of API documentation. Its modern interface, superior developer experience, and active development make it the right choice for .NET developers building APIs in 2025 and beyond."
- Microsoft .NET Team
Key Reasons for the Switch
- Better First Impressions: Swagger UI's dated interface doesn't reflect the modern capabilities of .NET
- Developer Productivity: Scalar's enhanced testing tools speed up API development and debugging
- OpenAPI 3.1 Alignment: Full support for the latest OpenAPI specification features
- Community Momentum: Growing adoption in the broader API ecosystem (not just .NET)
- Active Development: More frequent updates and feature additions compared to Swagger UI
π‘ Microsoft's Recommendation: While Swagger UI still works in .NET 9, Microsoft recommends using Scalar for all new projects. Existing projects are encouraged to migrate when feasible.
Implementation Guide
For .NET 9+ Projects (Default)
In .NET 9, Scalar is included by default when you create a new Web API project. Here's what's automatically configured:
dotnet new webapi -n MyApi
cd MyApi
dotnet run
Navigate to https://localhost:5001/scalar/v1 to see your API documentation.
What's Included Out of the Box
The default .NET 9 template includes:
Microsoft.AspNetCore.OpenApi- OpenAPI document generationScalar.AspNetCore- Scalar UI integration- Pre-configured middleware in
Program.cs - Sample weather forecast endpoints with XML documentation
For .NET 6, 7, 8 Projects (Manual Setup)
If you're using an earlier version of .NET, here's how to add Scalar to your existing project:
Step 1: Install NuGet Packages
dotnet add package Swashbuckle.AspNetCore
dotnet add package Scalar.AspNetCore
Step 2: Configure Services in Program.cs
using Scalar.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
// Add services
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "My API",
Version = "v1",
Description = "A comprehensive API for my application",
Contact = new OpenApiContact
{
Name = "Your Name",
Email = "[email protected]",
Url = new Uri("https://yourwebsite.com")
}
});
// Enable XML documentation (optional but recommended)
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
});
var app = builder.Build();
// Configure middleware
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.MapScalarApiReference(); // Scalar UI
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Step 3: Enable XML Documentation
To get rich API descriptions in Scalar, enable XML documentation in your .csproj file:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
Step 4: Run and Verify
dotnet run
Navigate to https://localhost:5001/scalar/v1 to see your Scalar documentation.
Advanced Configuration
Custom Theming
Scalar supports extensive theming to match your brand:
app.MapScalarApiReference(options =>
{
options.Theme = ScalarTheme.Mars; // Options: Default, Alternate, Moon, Purple, BluePlanet, Saturn, Kepler, Mars, DeepSpace, None
// Or use custom colors
options.CustomCss = @"
--scalar-color-1: #121212;
--scalar-color-2: #2a2a2a;
--scalar-color-3: #8b5cf6;
--scalar-color-accent: #8b5cf6;
";
options.Title = "My API Documentation";
options.Favicon = "/favicon.ico";
});
Multiple API Versions
Support multiple API versions with separate Scalar instances:
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "API v1", Version = "v1" });
options.SwaggerDoc("v2", new OpenApiInfo { Title = "API v2", Version = "v2" });
});
app.MapScalarApiReference(options =>
{
options.EndpointPrefix = "/docs/v1";
options.DocumentTitle = "API v1 Documentation";
}).WithName("v1");
app.MapScalarApiReference(options =>
{
options.EndpointPrefix = "/docs/v2";
options.DocumentTitle = "API v2 Documentation";
}).WithName("v2");
Authentication Configuration
Configure OAuth2 or API key authentication for testing:
builder.Services.AddSwaggerGen(options =>
{
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "Enter your JWT token"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
});
Content Security Policy (CSP) Fixes
β οΈ Common Issue: If you have strict Content Security Policy headers, Scalar may not load correctly due to inline scripts and styles. Here's how to fix it.
The Problem
Scalar uses inline JavaScript (unsafe-eval) and inline styles (unsafe-inline) for dynamic rendering. If your CSP policy blocks these, the UI will break.
Solution 1: Development-Only Exception (Recommended)
Only relax CSP in development environments:
app.Use(async (context, next) =>
{
if (app.Environment.IsDevelopment() && context.Request.Path.StartsWithSegments("/scalar"))
{
context.Response.Headers.Append("Content-Security-Policy",
"default-src 'self'; " +
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net; " +
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " +
"font-src 'self' https://fonts.gstatic.com; " +
"img-src 'self' data: https:; " +
"connect-src 'self' https:");
}
await next();
});
Solution 2: Nonce-Based CSP (Production)
For production environments, use nonces:
public class CspNonceMiddleware
{
private readonly RequestDelegate _next;
public async Task InvokeAsync(HttpContext context)
{
var nonce = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
context.Items["csp-nonce"] = nonce;
context.Response.Headers.Append("Content-Security-Policy",
$"script-src 'self' 'nonce-{nonce}'; style-src 'self' 'nonce-{nonce}'");
await _next(context);
}
}
// Register in Program.cs
app.UseMiddleware<CspNonceMiddleware>();
Solution 3: Separate Documentation Domain
Host documentation on a separate subdomain with relaxed CSP:
- Main API:
api.example.com(strict CSP) - Documentation:
docs.example.com(relaxed CSP for Scalar)
Common Issues & Troubleshooting
Issue 1: Scalar UI Shows Blank Page
Symptoms: Navigating to /scalar/v1 shows a blank white page or loading spinner.
Causes & Solutions:
- CSP Blocking: Check browser console for CSP violations. Apply one of the CSP fixes above.
- Missing Swagger JSON: Verify
/swagger/v1/swagger.jsonis accessible. Ensureapp.UseSwagger()is called beforeMapScalarApiReference(). - Incorrect Middleware Order: Make sure
UseSwagger()comes beforeMapScalarApiReference()in your middleware pipeline.
Issue 2: Endpoints Not Appearing
Symptoms: Scalar loads but doesn't show your API endpoints.
Causes & Solutions:
- Missing
AddEndpointsApiExplorer(): Addbuilder.Services.AddEndpointsApiExplorer();to your service configuration. - Controllers Not Registered: Ensure
builder.Services.AddControllers();andapp.MapControllers();are called. - Minimal API Endpoints: Use
.WithOpenApi()on minimal API endpoints:app.MapGet("/test", () => "Hello").WithOpenApi();
Issue 3: XML Documentation Not Showing
Symptoms: Endpoints appear but descriptions are missing.
Causes & Solutions:
- XML File Not Generated: Add
<GenerateDocumentationFile>true</GenerateDocumentationFile>to your.csproj. - XML File Not Found: Verify the XML file path in
IncludeXmlComments(xmlPath)matches the actual file location. - Missing XML Comments: Add
/// <summary>comments above your controllers and methods.
Issue 4: Dark Mode Not Working
Symptoms: Scalar doesn't respect dark mode preference.
Solution:
app.MapScalarApiReference(options =>
{
options.Theme = ScalarTheme.Moon; // Dark theme
options.DefaultOpenAllTags = true;
});
Migration from Swagger UI
Side-by-Side Approach (Recommended)
Run both Swagger UI and Scalar simultaneously during migration:
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "API v1 (Swagger UI)");
options.RoutePrefix = "swagger"; // Available at /swagger
});
app.MapScalarApiReference(options =>
{
options.EndpointPrefix = "/docs"; // Available at /docs/v1
options.Title = "API v1 Documentation (Scalar)";
});
}
This allows your team to compare both UIs and gradually transition.
Complete Replacement
To fully replace Swagger UI with Scalar:
// Remove Swagger UI
// app.UseSwaggerUI();
// Keep only Scalar
app.MapScalarApiReference();
Migration Checklist
- β Verify all endpoints appear in Scalar
- β Test authentication flows (if applicable)
- β Check XML documentation rendering
- β Validate request/response examples
- β Update internal documentation and links
- β Notify team members of the new documentation URL
- β Remove Swagger UI configuration after successful transition
Best Practices
1. Use XML Documentation
Always document your APIs with XML comments:
/// <summary>
/// Retrieves a specific user by ID
/// </summary>
/// <param name="id">The unique identifier of the user</param>
/// <returns>The requested user</returns>
/// <response code="200">User found successfully</response>
/// <response code="404">User not found</response>
[HttpGet("{id}")]
[ProducesResponseType(typeof(UserDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<UserDto>> GetUser(int id)
{
// Implementation
}
2. Environment-Specific Configuration
Only enable Scalar in development and staging:
if (!app.Environment.IsProduction())
{
app.UseSwagger();
app.MapScalarApiReference();
}
3. Customize for Your Brand
Match Scalar's appearance to your brand identity:
app.MapScalarApiReference(options =>
{
options.Title = "Acme Corp API Documentation";
options.Theme = ScalarTheme.Custom;
options.CustomCss = @"
--scalar-color-accent: #ff6b35;
--scalar-border-radius: 8px;
--scalar-font: 'Inter', sans-serif;
";
});
4. Use Tags for Organization
Group related endpoints with tags:
[ApiController]
[Route("api/[controller]")]
[Tags("Users")]
public class UsersController : ControllerBase
{
// Endpoints
}
5. Version Your API
Use URL versioning for clarity:
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class ProductsController : ControllerBase
{
// Endpoints
}
Conclusion
Scalar represents a significant step forward in API documentation tooling for .NET developers. Its modern interface, superior developer experience, and active development make it the clear choice for new projects in 2025.
Key Takeaways
- β Scalar is now the default in .NET 9 for good reason - it's faster, more intuitive, and better looking than Swagger UI
- β Migration is straightforward - you can run both side-by-side during the transition
- β CSP issues have clear solutions depending on your security requirements
- β XML documentation is essential for rich API descriptions
- β Extensive customization options let you match your brand identity
Next Steps
- πΉ Try Scalar in a test project to see the difference
- πΉ Review the official Scalar documentation
- πΉ Plan your migration timeline if you're on Swagger UI
- πΉ Share this guide with your team
π‘ Pro Tip: If you're starting a new .NET 9 project, you already have Scalar - just run dotnet new webapi and navigate to /scalar/v1 to see it in action!
Have questions or encountered issues with Scalar? Drop a comment below or reach out on GitHub!