Render Authenticated Web Pages to PDF Using Cookies
Most HTML-to-PDF jobs break for the same reason: the page only looks right after a user signs in. IronPDF drives a Chrome engine, so it sees what an unauthenticated browser would, a login screen or an empty shell, until you hand it the right cookies. Three pieces of the API solve this, the RequestContext property, the ApplyCookies method, and the CustomCookies dictionary. Here is where each one fits, with a snippet to match.
Rendering invoices and statements behind login
A customer's invoice sits on a session-protected route, and your application already holds their session. Pass that session ID straight through CustomCookies:
using IronPdf;
using System.Collections.Generic;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Global;
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "ASP.NET_SessionId", sessionId }
};
renderer.RenderUrlAsPdf("https://app.example.com/account/invoices/1042")
.SaveAs("invoice-1042.pdf");
using IronPdf;
using System.Collections.Generic;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Global;
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "ASP.NET_SessionId", sessionId }
};
renderer.RenderUrlAsPdf("https://app.example.com/account/invoices/1042")
.SaveAs("invoice-1042.pdf");
Imports IronPdf
Imports System.Collections.Generic
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Global
renderer.RenderingOptions.CustomCookies = New Dictionary(Of String, String) From {
{"ASP.NET_SessionId", sessionId}
}
renderer.RenderUrlAsPdf("https://app.example.com/account/invoices/1042").SaveAs("invoice-1042.pdf")
For basic or Windows authentication, reach for ApplyCookies instead. It signs in at the URL with the supplied credentials and captures the resulting cookies into the global context, which the following render then reuses:
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Global;
var credentials = new ChromeHttpLoginCredentials
{
NetworkUsername = "svc_reports",
NetworkPassword = "your_password"
};
string uri = "https://app.example.com/account/invoices/1042";
renderer.ApplyCookies(uri, credentials);
renderer.RenderUrlAsPdf(uri).SaveAs("invoice-1042.pdf");
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Global;
var credentials = new ChromeHttpLoginCredentials
{
NetworkUsername = "svc_reports",
NetworkPassword = "your_password"
};
string uri = "https://app.example.com/account/invoices/1042";
renderer.ApplyCookies(uri, credentials);
renderer.RenderUrlAsPdf(uri).SaveAs("invoice-1042.pdf");
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Global
Dim credentials As New ChromeHttpLoginCredentials With {
.NetworkUsername = "svc_reports",
.NetworkPassword = "your_password"
}
Dim uri As String = "https://app.example.com/account/invoices/1042"
renderer.ApplyCookies(uri, credentials)
renderer.RenderUrlAsPdf(uri).SaveAs("invoice-1042.pdf")
Token-based and third-party authentication
Modern apps rarely lean on simple HTTP credentials. They authenticate with JWTs, OAuth, or SAML, often storing the result in a cookie. Since CustomCookies takes any key-value pair, a bearer token or identity-provider cookie drops straight in:
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "auth_token", jwt },
{ "refresh_token", refreshToken }
};
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "auth_token", jwt },
{ "refresh_token", refreshToken }
};
Imports System.Collections.Generic
renderer.RenderingOptions.CustomCookies = New Dictionary(Of String, String) From {
{"auth_token", jwt},
{"refresh_token", refreshToken}
}
Personalized and localized documents
Cookies often carry locale, currency, or feature-flag state. Forward them, and the PDF matches what that specific user sees, in the correct language and currency:
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "locale", "en-AU" },
{ "currency", "AUD" },
{ "feature_newLayout", "on" }
};
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "locale", "en-AU" },
{ "currency", "AUD" },
{ "feature_newLayout", "on" }
};
renderer.RenderingOptions.CustomCookies = New Dictionary(Of String, String) From {
{"locale", "en-AU"},
{"currency", "AUD"},
{"feature_newLayout", "on"}
}
Batch generation that shares one session
To generate many PDFs for the same authenticated user in sequence, set RequestContext to Global. The browser state, cookies included, persists across renders, so you authenticate once instead of per document:
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Global;
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "ASP.NET_SessionId", sessionId }
};
foreach (var id in invoiceIds)
{
renderer.RenderUrlAsPdf($"https://app.example.com/invoices/{id}")
.SaveAs($"invoice-{id}.pdf");
}
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Global;
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "ASP.NET_SessionId", sessionId }
};
foreach (var id in invoiceIds)
{
renderer.RenderUrlAsPdf($"https://app.example.com/invoices/{id}")
.SaveAs($"invoice-{id}.pdf");
}
Imports IronPdf.Rendering
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.RequestContext = RequestContexts.Global
renderer.RenderingOptions.CustomCookies = New Dictionary(Of String, String) From {
{"ASP.NET_SessionId", sessionId}
}
For Each id In invoiceIds
renderer.RenderUrlAsPdf($"https://app.example.com/invoices/{id}").SaveAs($"invoice-{id}.pdf")
Next
Concurrent rendering without cookie bleed
The opposite scenario carries just as much weight. A service rendering for many different users at once needs Isolated context, which gives each render a clean state and stops one user's session from leaking into another's document. Give every thread its own renderer:
using System.Threading.Tasks;
Parallel.ForEach(jobs, job =>
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Isolated;
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "ASP.NET_SessionId", job.SessionId }
};
renderer.RenderUrlAsPdf(job.Url).SaveAs(job.OutputPath);
});
using System.Threading.Tasks;
Parallel.ForEach(jobs, job =>
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.RequestContext = IronPdf.Rendering.RequestContexts.Isolated;
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "ASP.NET_SessionId", job.SessionId }
};
renderer.RenderUrlAsPdf(job.Url).SaveAs(job.OutputPath);
});
Imports System.Threading.Tasks
Imports IronPdf.Rendering
Parallel.ForEach(jobs, Sub(job)
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.RequestContext = RequestContexts.Isolated
renderer.RenderingOptions.CustomCookies = New Dictionary(Of String, String) From {
{"ASP.NET_SessionId", job.SessionId}
}
renderer.RenderUrlAsPdf(job.Url).SaveAs(job.OutputPath)
End Sub)
Matching the method to the job
Use standard cookies (ApplyCookies) for basic HTTP auth, Windows authentication, and simple sessions. Reach for CustomCookies with tokens, multi-parameter sessions, third-party providers, and stored preferences. Pick Global to share state across renders and Isolated to keep them separate; Auto defaults to isolated and switches to global once ApplyCookies is called.
Most failures cluster around expired tokens, mismatched cookie domains, secure-cookie handling on HTTPS URLs, and SameSite policies on cross-origin requests. Confirm cookie validity before rendering, and lean on Global when sessions must persist.
When cookies are the whole job
Cookies are no edge case in PDF generation. Get them right and you ship a usable document; get them wrong and you ship a screenshot of a login form.
Frequently Asked Questions
How do I render a login-protected page as a PDF with IronPDF?
Set RequestContext to Global and populate CustomCookies with the user's session cookie before calling RenderUrlAsPdf. IronPDF's Chrome engine will authenticate with those cookies and render the protected page.
What is the difference between ApplyCookies and CustomCookies in IronPDF?
ApplyCookies signs in using HTTP credentials (basic auth or Windows auth) and captures the resulting session cookies into the global context. CustomCookies lets you supply cookie key-value pairs directly — useful for JWT tokens, OAuth cookies, and multi-parameter sessions.
What is RequestContext and when should I use Global vs Isolated?
Use Global when multiple renders share the same authenticated session (e.g., batch-generating invoices for one user). Use Isolated when rendering for many different users concurrently, so each render gets a clean cookie state and sessions cannot bleed between users.
Can IronPDF handle JWT and OAuth authentication for PDF rendering?
Yes. Pass the token values in CustomCookies as key-value pairs (e.g., auth_token and refresh_token). IronPDF forwards them with every request the Chrome engine makes for that render.
Why does my PDF render as a blank page or login screen?
The most common causes are expired session cookies, mismatched cookie domains, secure-cookie restrictions on HTTPS URLs, and SameSite policy blocks on cross-origin requests. Verify that the cookies are valid and match the target domain before rendering.

