Screenshots & PDFs from URLs in C# (.NET)

Published April 3, 2026 · 7 min read · URLSnap Team

Need to capture website screenshots or generate PDFs in a .NET application? Installing Playwright or Puppeteer in a C# project adds significant complexity — browser binaries, async lifecycle management, Linux dependency headaches in Docker. This guide shows a clean alternative: the URLSnap REST API, called with HttpClient from any .NET 6/8 project.

Prerequisites

Get a Free API Key

using System.Net.Http.Json;

using var http = new HttpClient();
var result = await http.PostAsJsonAsync(
    "https://urlsnap.dev/api/register",
    new { email = "you@example.com" }
);
var data = await result.Content.ReadFromJsonAsync<Dictionary<string, string>>();
Console.WriteLine(data!["key"]); // us_abc123...

Capture a Screenshot

using System.Net.Http.Headers;

const string ApiKey = "us_your_key_here";

async Task TakeScreenshot(string url, string outputPath, int width = 1280, int height = 800)
{
    using var http = new HttpClient();
    http.DefaultRequestHeaders.Add("x-api-key", ApiKey);

    var query = $"?url={Uri.EscapeDataString(url)}&width={width}&height={height}";
    var response = await http.GetAsync($"https://urlsnap.dev/api/screenshot{query}");
    response.EnsureSuccessStatusCode();

    var bytes = await response.Content.ReadAsByteArrayAsync();
    await File.WriteAllBytesAsync(outputPath, bytes);
    Console.WriteLine($"Saved {outputPath} ({bytes.Length / 1024} KB)");
}

// Full-page screenshot
await TakeScreenshot("https://example.com", "screenshot.png");

// Mobile viewport
await TakeScreenshot("https://urlsnap.dev", "mobile.png", width: 390, height: 844);
📸 Add &full=true to capture the full page height, not just the viewport.

Convert a URL to PDF

const string ApiKey = "us_your_key_here";

async Task UrlToPdf(string url, string outputPath, string format = "A4", bool landscape = false)
{
    using var http = new HttpClient();
    http.DefaultRequestHeaders.Add("x-api-key", ApiKey);

    var query = $"?url={Uri.EscapeDataString(url)}&format={format}&landscape={landscape.ToString().ToLower()}";
    var response = await http.GetAsync($"https://urlsnap.dev/api/pdf{query}");
    response.EnsureSuccessStatusCode();

    var bytes = await response.Content.ReadAsByteArrayAsync();
    await File.WriteAllBytesAsync(outputPath, bytes);
    Console.WriteLine($"PDF saved to {outputPath} ({bytes.Length / 1024} KB)");
}

// A4 PDF
await UrlToPdf("https://example.com", "page.pdf");

// Letter landscape
await UrlToPdf("https://en.wikipedia.org/wiki/C_Sharp_(programming_language)", "csharp-wiki.pdf", "Letter", landscape: true);

Convert HTML to PDF (Invoice / Report)

using System.Net.Http.Json;

const string ApiKey = "us_your_key_here";

async Task HtmlToPdf(string html, string outputPath, string format = "A4")
{
    using var http = new HttpClient();
    http.DefaultRequestHeaders.Add("x-api-key", ApiKey);

    var response = await http.PostAsJsonAsync(
        "https://urlsnap.dev/api/pdf",
        new { html, format }
    );
    response.EnsureSuccessStatusCode();

    var bytes = await response.Content.ReadAsByteArrayAsync();
    await File.WriteAllBytesAsync(outputPath, bytes);
}

var invoiceHtml = """
    <!DOCTYPE html>
    <html>
    <head>
      <style>
        body { font-family: sans-serif; padding: 40px; color: #111; }
        h1 { color: #6366f1; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { padding: 10px; border-bottom: 1px solid #eee; text-align: left; }
        .total { font-weight: bold; }
      </style>
    </head>
    <body>
      <h1>Invoice #INV-2026-001</h1>
      <p>Bill to: Acme Corp</p>
      <table>
        <tr><th>Item</th><th>Amount</th></tr>
        <tr><td>API Starter Plan</td><td>$9.00</td></tr>
        <tr class="total"><td>Total</td><td>$9.00</td></tr>
      </table>
    </body>
    </html>
    """;

await HtmlToPdf(invoiceHtml, "invoice.pdf");
Console.WriteLine("Invoice saved!");

ASP.NET Core — Serve PDF as File Download

// Program.cs (minimal API style)
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

const string ApiKey = "us_your_key_here";

app.MapGet("/download-pdf", async ([FromQuery] string url, HttpContext ctx) =>
{
    if (string.IsNullOrWhiteSpace(url))
        return Results.BadRequest(new { error = "url required" });

    using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };
    http.DefaultRequestHeaders.Add("x-api-key", ApiKey);

    var query = $"?url={Uri.EscapeDataString(url)}&format=A4";
    var upstream = await http.GetAsync($"https://urlsnap.dev/api/pdf{query}");

    if (!upstream.IsSuccessStatusCode)
    {
        var errBody = await upstream.Content.ReadAsStringAsync();
        return Results.Content(errBody, "application/json", statusCode: (int)upstream.StatusCode);
    }

    var bytes = await upstream.Content.ReadAsByteArrayAsync();
    return Results.File(bytes, "application/pdf", "page.pdf");
});

app.Run();
💡 Free plan: 20 req/day. Starter ($9/mo): 500 req/day. Pro ($29/mo): 5,000 req/day. Upgrade at urlsnap.dev/#pricing.

Check Your Quota

using var http = new HttpClient();
http.DefaultRequestHeaders.Add("x-api-key", "us_your_key_here");

var info = await http.GetFromJsonAsync<Dictionary<string, JsonElement>>("https://urlsnap.dev/api/me");
Console.WriteLine($"Plan: {info!["plan"]}");
Console.WriteLine($"Used today: {info["requests_today"]}/{info["daily_limit"]}");
Console.WriteLine($"Total: {info["requests_total"]}");

Error Handling

async Task<bool> SafeScreenshot(string url, string outputPath, string apiKey)
{
    try
    {
        using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };
        http.DefaultRequestHeaders.Add("x-api-key", apiKey);

        var query = $"?url={Uri.EscapeDataString(url)}&width=1280&height=800";
        var response = await http.GetAsync($"https://urlsnap.dev/api/screenshot{query}");

        if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
        {
            Console.WriteLine("Daily limit reached. Upgrade at urlsnap.dev/#pricing");
            return false;
        }
        if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
        {
            Console.WriteLine("Invalid API key.");
            return false;
        }

        response.EnsureSuccessStatusCode();

        var bytes = await response.Content.ReadAsByteArrayAsync();
        await File.WriteAllBytesAsync(outputPath, bytes);
        return true;
    }
    catch (TaskCanceledException)
    {
        Console.WriteLine("Request timed out.");
        return false;
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"HTTP error: {ex.Message}");
        return false;
    }
}

Start capturing screenshots and PDFs in C# today

Free tier: 20 requests/day. No NuGet packages, no browser binaries.

Get your free API key →