Skip to footer content
MIGRATION GUIDES

How to Migrate from Api2pdf to IronPDF in C#

Api2pdf offers a cloud-based service for generating PDFs, but sending sensitive documents to external servers can lead to security risks, compliance issues, and ongoing costs that can add up over time. This guide provides a detailed migration path from Api2pdf to IronPDF—a native .NET PDF library that processes documents entirely on your own infrastructure, removing data transmission concerns and converting per-conversion costs into a one-time investment.

Why Consider Moving from Api2pdf?

While Api2pdf provides convenient cloud-based PDF generation, several factors lead development teams to look for on-premises alternatives for their PDF generation needs.

Security and Compliance Concerns

Api2pdf operates as a cloud-based service where your sensitive HTML and documents are sent to third-party servers for processing. This creates significant concerns for organizations handling regulated data.

Risk Api2pdf IronPDF
Data Transmission All content sent to external servers Processes locally on your infrastructure
GDPR Compliance Data crosses jurisdictions Data never leaves your environment
HIPAA Compliance PHI transmitted externally PHI stays within your systems
SOC 2 Third-party dependency Full control over data handling
PCI DSS Card data potentially exposed No external transmission

Cost Accumulation Over Time

Api2pdf charges a $1/month base plus metered usage (bandwidth and compute seconds) indefinitely, while IronPDF offers a one-time perpetual license. Verify current numbers at api2pdf.com/pricing:

Component Api2pdf IronPDF
Base $1/month One-time license
Bandwidth $0.001 per MB n/a (local)
Compute $0.00019551 per second n/a (local)
Volume scaling Linear with usage and file size Flat (Lite ~$749, Plus ~$1,499, Professional ~$2,999)

Heavier workloads (large files, JS-heavy pages, long render times) shift the api2pdf bill upward; IronPDF cost is fixed once licensed.

Performance and Availability

Api2pdf requires network round-trips that add 2-5 seconds of latency to every PDF generation request. IronPDF processes locally in 100-500 milliseconds. Additionally, IronPDF works fully offline and in air-gapped environments—critical for applications that can't depend on external service availability.

Api2pdf vs. IronPDF: Key Differences

Aspect Api2pdf IronPDF
Data Handling Sent to third-party cloud servers Processed locally on your infrastructure
Pricing $1/month base + metered ($0.001/MB bandwidth, $0.00019551/sec compute) One-time perpetual license
Latency 2-5 seconds (network round-trip) 100-500ms (local processing)
Offline Not available Works fully offline
Installation API key + HTTP client Simple NuGet package
Compliance GDPR/HIPAA concerns (data leaves network) Full compliance control

Step-by-Step Migration Process

Step 1: Update NuGet Packages

Remove the Api2pdf package and install IronPDF:

# Remove Api2pdf
dotnet remove package Api2Pdf

# Install IronPDF
dotnet add package IronPdf
# Remove Api2pdf
dotnet remove package Api2Pdf

# Install IronPDF
dotnet add package IronPdf
SHELL

Or via Package Manager Console:

Uninstall-Package Api2Pdf
Install-Package IronPdf

Step 2: Update Namespace References

Replace Api2pdf namespaces with IronPDF:

// Remove these
using Api2Pdf;

// Add these
using IronPdf;
using IronPdf.Rendering;
// Remove these
using Api2Pdf;

// Add these
using IronPdf;
using IronPdf.Rendering;
Imports IronPdf
Imports IronPdf.Rendering
$vbLabelText   $csharpLabel

Step 3: Configure the License Key

Set the IronPDF license key at application startup:

// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";

// Or configure via appsettings.json:
// { "IronPdf.LicenseKey": "YOUR-IRONPDF-LICENSE-KEY" }
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";

// Or configure via appsettings.json:
// { "IronPdf.LicenseKey": "YOUR-IRONPDF-LICENSE-KEY" }
' Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY"

' Or configure via appsettings.json:
' { "IronPdf.LicenseKey": "YOUR-IRONPDF-LICENSE-KEY" }
$vbLabelText   $csharpLabel

Step 4: Remove API Key Configuration

IronPDF runs locally and doesn't require API keys:

// Remove this Api2pdf pattern
var client = new Api2Pdf("API_KEY");

// Just create the renderer directly
var renderer = new ChromePdfRenderer();
// Remove this Api2pdf pattern
var client = new Api2Pdf("API_KEY");

// Just create the renderer directly
var renderer = new ChromePdfRenderer();
' Remove this Api2pdf pattern
Dim client = New Api2Pdf("API_KEY")

' Just create the renderer directly
Dim renderer = New ChromePdfRenderer()
$vbLabelText   $csharpLabel

Complete API Migration Reference

Core Class Mapping

Api2pdf Class IronPDF Equivalent
Api2Pdf (client) ChromePdfRenderer
Api2PdfResult PdfDocument
ChromeHtmlToPdfOptions ChromePdfRenderOptions

Method Mapping

Api2pdf Method IronPDF Method
client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest { Html = html }) renderer.RenderHtmlAsPdf(html)
client.Chrome.UrlToPdfAsync(new ChromeUrlToPdfRequest { Url = url }) renderer.RenderUrlAsPdf(url)
result.FileUrl (URL to download) pdf.SaveAs(path)
result.GetFileBytes() pdf.BinaryData
client.PdfSharp.MergePdfs(new PdfMergeRequest { Urls = urls }) PdfDocument.Merge(pdfs)
client.PdfSharp.SetPassword(new PdfPasswordRequest { Url, OwnerPassword }) pdf.SecuritySettings.OwnerPassword

Rendering Options Mapping

Api2pdf Option IronPDF Option
Landscape = true RenderingOptions.PaperOrientation = Landscape
PreferCSSPageSize = true / Format RenderingOptions.PaperSize = PdfPaperSize.A4
PrintBackground = true RenderingOptions.PrintHtmlBackgrounds = true
MarginTop, etc. RenderingOptions.MarginTop, etc.
Delay = 5000 RenderingOptions.WaitFor.RenderDelay(5000)

Code Migration Examples

HTML to PDF Conversion

The most common Api2pdf operation demonstrates the fundamental shift—from cloud API calls to local processing.

Api2pdf Implementation:

// NuGet: Install-Package Api2Pdf
using System;
using System.Threading.Tasks;
using Api2Pdf;

class Program
{
    static async Task Main(string[] args)
    {
        var client = new Api2Pdf("your-api-key");
        var result = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
        {
            Html = "<h1>Hello World</h1>"
        });
        Console.WriteLine(result.FileUrl);
    }
}
// NuGet: Install-Package Api2Pdf
using System;
using System.Threading.Tasks;
using Api2Pdf;

class Program
{
    static async Task Main(string[] args)
    {
        var client = new Api2Pdf("your-api-key");
        var result = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
        {
            Html = "<h1>Hello World</h1>"
        });
        Console.WriteLine(result.FileUrl);
    }
}
Imports System
Imports System.Threading.Tasks
Imports Api2Pdf

Module Program
    Async Function Main(args As String()) As Task
        Dim client = New Api2Pdf("your-api-key")
        Dim result = Await client.Chrome.HtmlToPdfAsync(New ChromeHtmlToPdfRequest With {
            .Html = "<h1>Hello World</h1>"
        })
        Console.WriteLine(result.FileUrl)
    End Function
End Module
$vbLabelText   $csharpLabel

IronPDF Implementation:

// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created successfully");
    }
}
Imports System
Imports IronPdf

Class Program
    Shared Sub Main(ByVal args As String())
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>")
        pdf.SaveAs("output.pdf")
        Console.WriteLine("PDF created successfully")
    End Sub
End Class
$vbLabelText   $csharpLabel

IronPDF eliminates the network round-trip, API key management, and the separate download step required by Api2pdf's URL-based response pattern.

URL to PDF Conversion

Api2pdf Implementation:

// NuGet: Install-Package Api2Pdf
using System;
using System.Threading.Tasks;
using Api2Pdf;

class Program
{
    static async Task Main(string[] args)
    {
        var client = new Api2Pdf("your-api-key");
        var result = await client.Chrome.UrlToPdfAsync(new ChromeUrlToPdfRequest
        {
            Url = "https://www.example.com"
        });
        Console.WriteLine(result.FileUrl);
    }
}
// NuGet: Install-Package Api2Pdf
using System;
using System.Threading.Tasks;
using Api2Pdf;

class Program
{
    static async Task Main(string[] args)
    {
        var client = new Api2Pdf("your-api-key");
        var result = await client.Chrome.UrlToPdfAsync(new ChromeUrlToPdfRequest
        {
            Url = "https://www.example.com"
        });
        Console.WriteLine(result.FileUrl);
    }
}
Imports System
Imports System.Threading.Tasks
Imports Api2Pdf

Module Program
    Async Function Main(args As String()) As Task
        Dim client = New Api2Pdf("your-api-key")
        Dim result = Await client.Chrome.UrlToPdfAsync(New ChromeUrlToPdfRequest With {
            .Url = "https://www.example.com"
        })
        Console.WriteLine(result.FileUrl)
    End Function
End Module
$vbLabelText   $csharpLabel

IronPDF Implementation:

// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("PDF created from URL successfully");
    }
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
        Console.WriteLine("PDF created from URL successfully");
    }
}
Imports System
Imports IronPdf

Module Program
    Sub Main(args As String())
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
        pdf.SaveAs("webpage.pdf")
        Console.WriteLine("PDF created from URL successfully")
    End Sub
End Module
$vbLabelText   $csharpLabel

HTML File to PDF with Options

Api2pdf Implementation:

// NuGet: Install-Package Api2Pdf
using System;
using System.IO;
using System.Threading.Tasks;
using Api2Pdf;

class Program
{
    static async Task Main(string[] args)
    {
        var client = new Api2Pdf("your-api-key");
        string html = File.ReadAllText("input.html");
        var result = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
        {
            Html = html,
            Options = new ChromeHtmlToPdfOptions
            {
                Landscape = true,
                PrintBackground = true
            }
        });
        Console.WriteLine(result.FileUrl);
    }
}
// NuGet: Install-Package Api2Pdf
using System;
using System.IO;
using System.Threading.Tasks;
using Api2Pdf;

class Program
{
    static async Task Main(string[] args)
    {
        var client = new Api2Pdf("your-api-key");
        string html = File.ReadAllText("input.html");
        var result = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
        {
            Html = html,
            Options = new ChromeHtmlToPdfOptions
            {
                Landscape = true,
                PrintBackground = true
            }
        });
        Console.WriteLine(result.FileUrl);
    }
}
Imports System
Imports System.IO
Imports System.Threading.Tasks
Imports Api2Pdf

Module Program
    Async Function Main(args As String()) As Task
        Dim client = New Api2Pdf("your-api-key")
        Dim html As String = File.ReadAllText("input.html")
        Dim result = Await client.Chrome.HtmlToPdfAsync(New ChromeHtmlToPdfRequest With {
            .Html = html,
            .Options = New ChromeHtmlToPdfOptions With {
                .Landscape = True,
                .PrintBackground = True
            }
        })
        Console.WriteLine(result.FileUrl)
    End Function
End Module
$vbLabelText   $csharpLabel

IronPDF Implementation:

// NuGet: Install-Package IronPdf
using System;
using System.IO;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;
        string html = File.ReadAllText("input.html");
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created with options successfully");
    }
}
// NuGet: Install-Package IronPdf
using System;
using System.IO;
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;
        string html = File.ReadAllText("input.html");
        var pdf = renderer.RenderHtmlAsPdf(html);
        pdf.SaveAs("output.pdf");
        Console.WriteLine("PDF created with options successfully");
    }
}
Imports System
Imports System.IO
Imports IronPdf

Module Program
    Sub Main(args As String())
        Dim renderer As New ChromePdfRenderer()
        renderer.RenderingOptions.PaperOrientation = IronPdf.Rendering.PdfPaperOrientation.Landscape
        renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print
        Dim html As String = File.ReadAllText("input.html")
        Dim pdf = renderer.RenderHtmlAsPdf(html)
        pdf.SaveAs("output.pdf")
        Console.WriteLine("PDF created with options successfully")
    End Sub
End Module
$vbLabelText   $csharpLabel

IronPDF configures rendering options directly on the renderer object rather than passing them as a separate options parameter to each API call.

Merging Multiple PDFs

Api2pdf Implementation:

using Api2Pdf;

var client = new Api2Pdf("YOUR_API_KEY");

var pdfUrls = new List<string>
{
    "https://example.com/pdf1.pdf",
    "https://example.com/pdf2.pdf",
    "https://example.com/pdf3.pdf"
};

var request = new PdfMergeRequest { Urls = pdfUrls };
var result = await client.PdfSharp.MergePdfsAsync(request);

if (result.Success)
{
    // Download merged PDF from result.FileUrl
}
using Api2Pdf;

var client = new Api2Pdf("YOUR_API_KEY");

var pdfUrls = new List<string>
{
    "https://example.com/pdf1.pdf",
    "https://example.com/pdf2.pdf",
    "https://example.com/pdf3.pdf"
};

var request = new PdfMergeRequest { Urls = pdfUrls };
var result = await client.PdfSharp.MergePdfsAsync(request);

if (result.Success)
{
    // Download merged PDF from result.FileUrl
}
Imports Api2Pdf

Dim client As New Api2Pdf("YOUR_API_KEY")

Dim pdfUrls As New List(Of String) From {
    "https://example.com/pdf1.pdf",
    "https://example.com/pdf2.pdf",
    "https://example.com/pdf3.pdf"
}

Dim request As New PdfMergeRequest With {.Urls = pdfUrls}
Dim result = Await client.PdfSharp.MergePdfsAsync(request)

If result.Success Then
    ' Download merged PDF from result.FileUrl
End If
$vbLabelText   $csharpLabel

IronPDF Implementation:

using IronPdf;

// Load PDFs from files
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var pdf3 = PdfDocument.FromFile("document3.pdf");

// Merge all PDFs
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("merged.pdf");
using IronPdf;

// Load PDFs from files
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var pdf3 = PdfDocument.FromFile("document3.pdf");

// Merge all PDFs
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("merged.pdf");
Imports IronPdf

' Load PDFs from files
Dim pdf1 = PdfDocument.FromFile("document1.pdf")
Dim pdf2 = PdfDocument.FromFile("document2.pdf")
Dim pdf3 = PdfDocument.FromFile("document3.pdf")

' Merge all PDFs
Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
merged.SaveAs("merged.pdf")
$vbLabelText   $csharpLabel

IronPDF's static Merge method accepts multiple documents directly, eliminating the URL-based workflow.

Password-Protected PDFs

Api2pdf Implementation:

using Api2Pdf;

var client = new Api2Pdf("YOUR_API_KEY");

// Generate PDF first
var pdfResult = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
{
    Html = "<h1>Confidential</h1>"
});

// Then add password protection in a second round-trip
var protectedResult = await client.PdfSharp.SetPasswordAsync(new PdfPasswordRequest
{
    Url = pdfResult.FileUrl,
    OwnerPassword = "secretpassword"
});
using Api2Pdf;

var client = new Api2Pdf("YOUR_API_KEY");

// Generate PDF first
var pdfResult = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
{
    Html = "<h1>Confidential</h1>"
});

// Then add password protection in a second round-trip
var protectedResult = await client.PdfSharp.SetPasswordAsync(new PdfPasswordRequest
{
    Url = pdfResult.FileUrl,
    OwnerPassword = "secretpassword"
});
Imports Api2Pdf

Dim client = New Api2Pdf("YOUR_API_KEY")

' Generate PDF first
Dim pdfResult = Await client.Chrome.HtmlToPdfAsync(New ChromeHtmlToPdfRequest With {
    .Html = "<h1>Confidential</h1>"
})

' Then add password protection in a second round-trip
Dim protectedResult = Await client.PdfSharp.SetPasswordAsync(New PdfPasswordRequest With {
    .Url = pdfResult.FileUrl,
    .OwnerPassword = "secretpassword"
})
$vbLabelText   $csharpLabel

IronPDF Implementation:

using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");

// Set security in one step
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user123";
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;

pdf.SaveAs("protected.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");

// Set security in one step
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user123";
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;

pdf.SaveAs("protected.pdf");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>")

' Set security in one step
pdf.SecuritySettings.OwnerPassword = "owner123"
pdf.SecuritySettings.UserPassword = "user123"
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit

pdf.SaveAs("protected.pdf")
$vbLabelText   $csharpLabel

IronPDF provides granular control over PDF permissions through the SecuritySettings property.

Headers and Footers

Api2pdf Implementation:

using Api2Pdf;

var client = new Api2Pdf("YOUR_API_KEY");

var result = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
{
    Html = html,
    Options = new ChromeHtmlToPdfOptions
    {
        DisplayHeaderFooter = true,
        HeaderTemplate = "<div style='font-size:10px'>Company Header</div>",
        FooterTemplate = "<div style='font-size:10px'>Page <span class='pageNumber'></span></div>"
    }
});
using Api2Pdf;

var client = new Api2Pdf("YOUR_API_KEY");

var result = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
{
    Html = html,
    Options = new ChromeHtmlToPdfOptions
    {
        DisplayHeaderFooter = true,
        HeaderTemplate = "<div style='font-size:10px'>Company Header</div>",
        FooterTemplate = "<div style='font-size:10px'>Page <span class='pageNumber'></span></div>"
    }
});
Imports Api2Pdf

Dim client = New Api2Pdf("YOUR_API_KEY")

Dim result = Await client.Chrome.HtmlToPdfAsync(New ChromeHtmlToPdfRequest With {
    .Html = html,
    .Options = New ChromeHtmlToPdfOptions With {
        .DisplayHeaderFooter = True,
        .HeaderTemplate = "<div style='font-size:10px'>Company Header</div>",
        .FooterTemplate = "<div style='font-size:10px'>Page <span class='pageNumber'></span></div>"
    }
})
$vbLabelText   $csharpLabel

IronPDF Implementation:

using IronPdf;

var renderer = new ChromePdfRenderer();

// HTML headers and footers with full styling
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:10px; text-align:center;'>Company Header</div>",
    DrawDividerLine = true
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:10px; text-align:center;'>Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("with-headers.pdf");
using IronPdf;

var renderer = new ChromePdfRenderer();

// HTML headers and footers with full styling
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:10px; text-align:center;'>Company Header</div>",
    DrawDividerLine = true
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:10px; text-align:center;'>Page {page} of {total-pages}</div>",
    DrawDividerLine = true
};

var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("with-headers.pdf");
Imports IronPdf

Dim renderer As New ChromePdfRenderer()

' HTML headers and footers with full styling
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='font-size:10px; text-align:center;'>Company Header</div>",
    .DrawDividerLine = True
}

renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='font-size:10px; text-align:center;'>Page {page} of {total-pages}</div>",
    .DrawDividerLine = True
}

Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("with-headers.pdf")
$vbLabelText   $csharpLabel

IronPDF supports placeholder tokens like {page} and {total-pages} for dynamic page numbering. For more options, see the headers and footers documentation.

ASP.NET Core Integration

Api2pdf's async HTTP pattern differs significantly from IronPDF's direct PDF generation.

Api2pdf Pattern:

[ApiController]
public class PdfController : ControllerBase
{
    private readonly Api2Pdf _client;

    public PdfController()
    {
        _client = new Api2Pdf("YOUR_API_KEY");
    }

    [HttpGet("generate")]
    public async Task<IActionResult> GeneratePdf()
    {
        var result = await _client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
        {
            Html = "<h1>Report</h1>"
        });

        if (!result.Success)
            return BadRequest(result.Error);

        // Redirect to download URL
        return Redirect(result.FileUrl);
    }
}
[ApiController]
public class PdfController : ControllerBase
{
    private readonly Api2Pdf _client;

    public PdfController()
    {
        _client = new Api2Pdf("YOUR_API_KEY");
    }

    [HttpGet("generate")]
    public async Task<IActionResult> GeneratePdf()
    {
        var result = await _client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest
        {
            Html = "<h1>Report</h1>"
        });

        if (!result.Success)
            return BadRequest(result.Error);

        // Redirect to download URL
        return Redirect(result.FileUrl);
    }
}
Imports Microsoft.AspNetCore.Mvc

<ApiController>
Public Class PdfController
    Inherits ControllerBase

    Private ReadOnly _client As Api2Pdf

    Public Sub New()
        _client = New Api2Pdf("YOUR_API_KEY")
    End Sub

    <HttpGet("generate")>
    Public Async Function GeneratePdf() As Task(Of IActionResult)
        Dim result = Await _client.Chrome.HtmlToPdfAsync(New ChromeHtmlToPdfRequest With {
            .Html = "<h1>Report</h1>"
        })

        If Not result.Success Then
            Return BadRequest(result.Error)
        End If

        ' Redirect to download URL
        Return Redirect(result.FileUrl)
    End Function
End Class
$vbLabelText   $csharpLabel

IronPDF Pattern:

[ApiController]
public class PdfController : ControllerBase
{
    [HttpGet("generate")]
    public IActionResult GeneratePdf()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>");

        // Return PDF directly - no download step needed
        return File(pdf.BinaryData, "application/pdf", "report.pdf");
    }

    [HttpGet("generate-async")]
    public async Task<IActionResult> GeneratePdfAsync()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Report</h1>");

        return File(pdf.BinaryData, "application/pdf", "report.pdf");
    }
}
[ApiController]
public class PdfController : ControllerBase
{
    [HttpGet("generate")]
    public IActionResult GeneratePdf()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>");

        // Return PDF directly - no download step needed
        return File(pdf.BinaryData, "application/pdf", "report.pdf");
    }

    [HttpGet("generate-async")]
    public async Task<IActionResult> GeneratePdfAsync()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Report</h1>");

        return File(pdf.BinaryData, "application/pdf", "report.pdf");
    }
}
Imports Microsoft.AspNetCore.Mvc

<ApiController>
Public Class PdfController
    Inherits ControllerBase

    <HttpGet("generate")>
    Public Function GeneratePdf() As IActionResult
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Report</h1>")

        ' Return PDF directly - no download step needed
        Return File(pdf.BinaryData, "application/pdf", "report.pdf")
    End Function

    <HttpGet("generate-async")>
    Public Async Function GeneratePdfAsync() As Task(Of IActionResult)
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = Await renderer.RenderHtmlAsPdfAsync("<h1>Report</h1>")

        Return File(pdf.BinaryData, "application/pdf", "report.pdf")
    End Function
End Class
$vbLabelText   $csharpLabel

IronPDF returns the PDF directly via BinaryData or Stream, eliminating the redirect-to-download pattern.

Dependency Injection Configuration

// Program.cs or Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IPdfService, IronPdfService>();
}

// IPdfService.cs
public interface IPdfService
{
    PdfDocument GenerateFromHtml(string html);
    Task<PdfDocument> GenerateFromHtmlAsync(string html);
}

// IronPdfService.cs
public class IronPdfService : IPdfService
{
    private readonly ChromePdfRenderer _renderer;

    public IronPdfService()
    {
        _renderer = new ChromePdfRenderer();
        _renderer.RenderingOptions.PrintHtmlBackgrounds = true;
        _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
    }

    public PdfDocument GenerateFromHtml(string html) =>
        _renderer.RenderHtmlAsPdf(html);

    public Task<PdfDocument> GenerateFromHtmlAsync(string html) =>
        _renderer.RenderHtmlAsPdfAsync(html);
}
// Program.cs or Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IPdfService, IronPdfService>();
}

// IPdfService.cs
public interface IPdfService
{
    PdfDocument GenerateFromHtml(string html);
    Task<PdfDocument> GenerateFromHtmlAsync(string html);
}

// IronPdfService.cs
public class IronPdfService : IPdfService
{
    private readonly ChromePdfRenderer _renderer;

    public IronPdfService()
    {
        _renderer = new ChromePdfRenderer();
        _renderer.RenderingOptions.PrintHtmlBackgrounds = true;
        _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
    }

    public PdfDocument GenerateFromHtml(string html) =>
        _renderer.RenderHtmlAsPdf(html);

    public Task<PdfDocument> GenerateFromHtmlAsync(string html) =>
        _renderer.RenderHtmlAsPdfAsync(html);
}
' Program.vb or Startup.vb
Public Sub ConfigureServices(services As IServiceCollection)
    services.AddScoped(Of IPdfService, IronPdfService)()
End Sub

' IPdfService.vb
Public Interface IPdfService
    Function GenerateFromHtml(html As String) As PdfDocument
    Function GenerateFromHtmlAsync(html As String) As Task(Of PdfDocument)
End Interface

' IronPdfService.vb
Public Class IronPdfService
    Implements IPdfService

    Private ReadOnly _renderer As ChromePdfRenderer

    Public Sub New()
        _renderer = New ChromePdfRenderer()
        _renderer.RenderingOptions.PrintHtmlBackgrounds = True
        _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
    End Sub

    Public Function GenerateFromHtml(html As String) As PdfDocument Implements IPdfService.GenerateFromHtml
        Return _renderer.RenderHtmlAsPdf(html)
    End Function

    Public Function GenerateFromHtmlAsync(html As String) As Task(Of PdfDocument) Implements IPdfService.GenerateFromHtmlAsync
        Return _renderer.RenderHtmlAsPdfAsync(html)
    End Function
End Class
$vbLabelText   $csharpLabel

Error Handling Migration

Api2pdf uses response object checks. IronPDF uses standard .NET exceptions.

Api2pdf Pattern:

var result = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest { Html = html });

if (!result.Success)
{
    Console.WriteLine($"Error: {result.Error}");
    return;
}
var result = await client.Chrome.HtmlToPdfAsync(new ChromeHtmlToPdfRequest { Html = html });

if (!result.Success)
{
    Console.WriteLine($"Error: {result.Error}");
    return;
}
Imports System

Dim result = Await client.Chrome.HtmlToPdfAsync(New ChromeHtmlToPdfRequest With {.Html = html})

If Not result.Success Then
    Console.WriteLine($"Error: {result.Error}")
    Return
End If
$vbLabelText   $csharpLabel

IronPDF Pattern:

try
{
    var renderer = new ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs("output.pdf");
}
catch (IronPdf.Exceptions.IronPdfLicenseException ex)
{
    Console.WriteLine($"License error: {ex.Message}");
}
catch (IronPdf.Exceptions.IronPdfRenderingException ex)
{
    Console.WriteLine($"Rendering error: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
try
{
    var renderer = new ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs("output.pdf");
}
catch (IronPdf.Exceptions.IronPdfLicenseException ex)
{
    Console.WriteLine($"License error: {ex.Message}");
}
catch (IronPdf.Exceptions.IronPdfRenderingException ex)
{
    Console.WriteLine($"Rendering error: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
Imports IronPdf.Exceptions

Try
    Dim renderer = New ChromePdfRenderer()
    Dim pdf = renderer.RenderHtmlAsPdf(html)
    pdf.SaveAs("output.pdf")
Catch ex As IronPdfLicenseException
    Console.WriteLine($"License error: {ex.Message}")
Catch ex As IronPdfRenderingException
    Console.WriteLine($"Rendering error: {ex.Message}")
Catch ex As Exception
    Console.WriteLine($"Error: {ex.Message}")
End Try
$vbLabelText   $csharpLabel

Performance Comparison

Metric Api2pdf IronPDF
Simple HTML 2-5 seconds (network) 100-500ms (local)
Complex page 5-10 seconds 500ms-2s
Batch of 100 Minutes (rate limits) Seconds (parallel)
Offline Not available Works fully
Cold start None ~2s (first render)

Performance Optimization Tips

// 1. Reuse renderer instance
private static readonly ChromePdfRenderer SharedRenderer = new ChromePdfRenderer();

public PdfDocument GeneratePdf(string html)
{
    return SharedRenderer.RenderHtmlAsPdf(html);
}

// 2. Parallel generation
var tasks = htmlDocs.Select(html =>
    Task.Run(() => SharedRenderer.RenderHtmlAsPdf(html)));
var results = await Task.WhenAll(tasks);

// 3. Disable unnecessary features for speed
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = false; // If not needed
renderer.RenderingOptions.WaitFor.RenderDelay(0);   // No delay
// 1. Reuse renderer instance
private static readonly ChromePdfRenderer SharedRenderer = new ChromePdfRenderer();

public PdfDocument GeneratePdf(string html)
{
    return SharedRenderer.RenderHtmlAsPdf(html);
}

// 2. Parallel generation
var tasks = htmlDocs.Select(html =>
    Task.Run(() => SharedRenderer.RenderHtmlAsPdf(html)));
var results = await Task.WhenAll(tasks);

// 3. Disable unnecessary features for speed
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = false; // If not needed
renderer.RenderingOptions.WaitFor.RenderDelay(0);   // No delay
Imports System.Threading.Tasks

' 1. Reuse renderer instance
Private Shared ReadOnly SharedRenderer As New ChromePdfRenderer()

Public Function GeneratePdf(html As String) As PdfDocument
    Return SharedRenderer.RenderHtmlAsPdf(html)
End Function

' 2. Parallel generation
Dim tasks = htmlDocs.Select(Function(html) Task.Run(Function() SharedRenderer.RenderHtmlAsPdf(html)))
Dim results = Await Task.WhenAll(tasks)

' 3. Disable unnecessary features for speed
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.EnableJavaScript = False ' If not needed
renderer.RenderingOptions.WaitFor.RenderDelay(0) ' No delay
$vbLabelText   $csharpLabel

Troubleshooting Common Migration Issues

Issue: PDF Looks Different from Api2pdf Output

Match Api2pdf's Headless Chrome settings:

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
renderer.RenderingOptions.PrintHtmlBackgrounds = true;
renderer.RenderingOptions.ViewPortWidth = 1280;
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.WaitFor.RenderDelay(1000);
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
renderer.RenderingOptions.PrintHtmlBackgrounds = true;
renderer.RenderingOptions.ViewPortWidth = 1280;
renderer.RenderingOptions.EnableJavaScript = true;
renderer.RenderingOptions.WaitFor.RenderDelay(1000);
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print
renderer.RenderingOptions.PrintHtmlBackgrounds = True
renderer.RenderingOptions.ViewPortWidth = 1280
renderer.RenderingOptions.EnableJavaScript = True
renderer.RenderingOptions.WaitFor.RenderDelay(1000)
$vbLabelText   $csharpLabel

Issue: External Resources Not Loading

Configure resource loading timeouts:

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.AllFontsLoaded(timeout: 10000);
renderer.RenderingOptions.WaitFor.NetworkIdle(timeout: 10000);

// Or use base URL for relative paths
var pdf = renderer.RenderHtmlAsPdf(html, baseUrl: "https://example.com/");
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.AllFontsLoaded(timeout: 10000);
renderer.RenderingOptions.WaitFor.NetworkIdle(timeout: 10000);

// Or use base URL for relative paths
var pdf = renderer.RenderHtmlAsPdf(html, baseUrl: "https://example.com/");
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.WaitFor.AllFontsLoaded(timeout:=10000)
renderer.RenderingOptions.WaitFor.NetworkIdle(timeout:=10000)

' Or use base URL for relative paths
Dim pdf = renderer.RenderHtmlAsPdf(html, baseUrl:="https://example.com/")
$vbLabelText   $csharpLabel

Issue: Large PDF File Sizes

Compress images after generation:

renderer.RenderingOptions.ImageQuality = 80;

// Or compress after generation
pdf.CompressImages(quality: 75);
pdf.SaveAs("compressed.pdf");
renderer.RenderingOptions.ImageQuality = 80;

// Or compress after generation
pdf.CompressImages(quality: 75);
pdf.SaveAs("compressed.pdf");
renderer.RenderingOptions.ImageQuality = 80

' Or compress after generation
pdf.CompressImages(quality:=75)
pdf.SaveAs("compressed.pdf")
$vbLabelText   $csharpLabel

Post-Migration Checklist

After completing the code migration, verify the following:

  • Verify PDF output quality matches expectations
  • Test all edge cases (large documents, special characters)
  • Validate performance metrics (should see significant improvement)
  • Update Docker configurations if applicable
  • Remove Api2pdf portal account and API keys
  • Update monitoring (no more API latency tracking needed)
  • Document new patterns for your team
  • Update CI/CD pipelines

Additional Resources


Migrating from Api2pdf to IronPDF transforms your PDF generation from a cloud-dependent, per-conversion cost model to a local, one-time investment. Your sensitive documents stay on your infrastructure, latency drops from seconds to milliseconds, and you eliminate vendor dependency for this critical application capability.

Please noteAPI2PDF and PDFSharp are registered trademarks of their respective owners. This site is not affiliated with, endorsed by, or sponsored by Api2Pdf or empira Software GmbH. All product names, logos, and brands are property of their respective owners. Comparisons are for informational purposes only and reflect publicly available information at the time of writing.

Curtis Chau
Technical Writer

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.

...

Read More

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me