How to OCR documents on AWS Lambda
This how-to article provides a step-by-step guide for setting up an AWS Lambda function using IronOCR. By following this guide, you will learn how to configure IronOCR and efficiently read documents stored in an S3 bucket.
How to OCR documents on AWS Lambda
- Download a C# library to perform OCR on documents
- Create and choose the project template
- Modify the FunctionHandler code
- Configure and deploy the project
- Invoke the function and check the results in S3
Installation
This article will use an S3 bucket, so the AWSSDK.S3 package is required.
If you are using IronOCR ZIP, it is essential to set the temporary folder.
// Set temporary folder path and log file path for IronOCR.
var awsTmpPath = @"/tmp/";
IronOcr.Installation.InstallationPath = awsTmpPath;
IronOcr.Installation.LogFilePath = awsTmpPath;' Set temporary folder path and log file path for IronOCR.
Dim awsTmpPath As String = "/tmp/"
IronOcr.Installation.InstallationPath = awsTmpPath
IronOcr.Installation.LogFilePath = awsTmpPathStart using IronOCR in your project today with a free trial.
Create an AWS Lambda Project
With Visual Studio, creating a containerized AWS Lambda is an easy process:
- Install the AWS Toolkit for Visual Studio.
- Select an 'AWS Lambda Project (.NET Core - C#)'.
- Select a '.NET 8 (Container Image)' blueprint, then select 'Finish'.

Add Package Dependencies
Using the IronOCR library in .NET 8 does not require additional dependencies to be installed for use on AWS Lambda. Modify the project's Dockerfile with the following:
FROM public.ecr.aws/lambda/dotnet:8
# Update all installed packages
RUN dnf update -y
WORKDIR /var/task
# Copy build artifacts from the host machine into the Docker image
COPY "bin/Release/lambda-publish" .
Modify the FunctionHandler Code
This example retrieves an image from an S3 bucket, processes it, and saves a searchable PDF back to the same bucket. Setting the temp folder is essential when using IronOCR ZIP, as the library requires write permissions to copy the runtime folder from the DLLs.
using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;
using IronOcr;
using System;
using System.IO;
using System.Threading.Tasks;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace IronOcrZipAwsLambda
{
public class Function
{
// Initialize the S3 client with a specific region endpoint
private static readonly IAmazonS3 _s3Client = new AmazonS3Client(Amazon.RegionEndpoint.APSoutheast1);
/// <summary>
/// Function handler to process OCR on the PDF stored in S3.
/// </summary>
/// <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
public async Task FunctionHandler(ILambdaContext context)
{
// Set up necessary paths for IronOCR
var awsTmpPath = @"/tmp/";
IronOcr.Installation.InstallationPath = awsTmpPath;
IronOcr.Installation.LogFilePath = awsTmpPath;
// Set license key for IronOCR
IronOcr.License.LicenseKey = "IRONOCR-MYLICENSE-KEY-1EF01";
string bucketName = "deploymenttestbucket"; // Your bucket name
string pdfName = "sample";
string objectKey = $"IronPdfZip/{pdfName}.pdf";
string objectKeyForSearchablePdf = $"IronPdfZip/{pdfName}-SearchablePdf.pdf";
try
{
// Retrieve the PDF file from S3
var pdfData = await GetPdfFromS3Async(bucketName, objectKey);
// Initialize IronTesseract for OCR processing
IronTesseract ironTesseract = new IronTesseract();
OcrInput ocrInput = new OcrInput();
ocrInput.LoadPdf(pdfData);
OcrResult result = ironTesseract.Read(ocrInput);
// Log the OCR result
context.Logger.LogLine($"OCR result: {result.Text}");
// Upload the searchable PDF to S3
await UploadPdfToS3Async(bucketName, objectKeyForSearchablePdf, result.SaveAsSearchablePdfBytes());
context.Logger.LogLine($"PDF uploaded successfully to {bucketName}/{objectKeyForSearchablePdf}");
}
catch (Exception e)
{
context.Logger.LogLine($"[ERROR] FunctionHandler: {e.Message}");
}
}
/// <summary>
/// Retrieves a PDF from S3 and returns it as a byte array.
/// </summary>
private async Task<byte[]> GetPdfFromS3Async(string bucketName, string objectKey)
{
var request = new GetObjectRequest
{
BucketName = bucketName,
Key = objectKey
};
using (var response = await _s3Client.GetObjectAsync(request))
using (var memoryStream = new MemoryStream())
{
await response.ResponseStream.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
}
/// <summary>
/// Uploads the generated searchable PDF back to S3.
/// </summary>
private async Task UploadPdfToS3Async(string bucketName, string objectKey, byte[] pdfBytes)
{
using (var memoryStream = new MemoryStream(pdfBytes))
{
var request = new PutObjectRequest
{
BucketName = bucketName,
Key = objectKey,
InputStream = memoryStream,
ContentType = "application/pdf"
};
await _s3Client.PutObjectAsync(request);
}
}
}
}Imports Amazon.Lambda.Core
Imports Amazon.S3
Imports Amazon.S3.Model
Imports IronOcr
Imports System
Imports System.IO
Imports System.Threading.Tasks
' Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
<Assembly: LambdaSerializer(GetType(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))>
Namespace IronOcrZipAwsLambda
Public Class [Function]
' Initialize the S3 client with a specific region endpoint
Private Shared ReadOnly _s3Client As IAmazonS3 = New AmazonS3Client(Amazon.RegionEndpoint.APSoutheast1)
''' <summary>
''' Function handler to process OCR on the PDF stored in S3.
''' </summary>
''' <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
Public Async Function FunctionHandler(ByVal context As ILambdaContext) As Task
' Set up necessary paths for IronOCR
Dim awsTmpPath = "/tmp/"
IronOcr.Installation.InstallationPath = awsTmpPath
IronOcr.Installation.LogFilePath = awsTmpPath
' Set license key for IronOCR
IronOcr.License.LicenseKey = "IRONOCR-MYLICENSE-KEY-1EF01"
Dim bucketName As String = "deploymenttestbucket" ' Your bucket name
Dim pdfName As String = "sample"
Dim objectKey As String = $"IronPdfZip/{pdfName}.pdf"
Dim objectKeyForSearchablePdf As String = $"IronPdfZip/{pdfName}-SearchablePdf.pdf"
Try
' Retrieve the PDF file from S3
Dim pdfData = Await GetPdfFromS3Async(bucketName, objectKey)
' Initialize IronTesseract for OCR processing
Dim ironTesseract As New IronTesseract()
Dim ocrInput As New OcrInput()
ocrInput.LoadPdf(pdfData)
Dim result As OcrResult = ironTesseract.Read(ocrInput)
' Log the OCR result
context.Logger.LogLine($"OCR result: {result.Text}")
' Upload the searchable PDF to S3
Await UploadPdfToS3Async(bucketName, objectKeyForSearchablePdf, result.SaveAsSearchablePdfBytes())
context.Logger.LogLine($"PDF uploaded successfully to {bucketName}/{objectKeyForSearchablePdf}")
Catch e As Exception
context.Logger.LogLine($"[ERROR] FunctionHandler: {e.Message}")
End Try
End Function
''' <summary>
''' Retrieves a PDF from S3 and returns it as a byte array.
''' </summary>
Private Async Function GetPdfFromS3Async(ByVal bucketName As String, ByVal objectKey As String) As Task(Of Byte())
Dim request = New GetObjectRequest With {
.BucketName = bucketName,
.Key = objectKey
}
Using response = Await _s3Client.GetObjectAsync(request)
Using memoryStream As New MemoryStream()
Await response.ResponseStream.CopyToAsync(memoryStream)
Return memoryStream.ToArray()
End Using
End Using
End Function
''' <summary>
''' Uploads the generated searchable PDF back to S3.
''' </summary>
Private Async Function UploadPdfToS3Async(ByVal bucketName As String, ByVal objectKey As String, ByVal pdfBytes() As Byte) As Task
Using memoryStream As New MemoryStream(pdfBytes)
Dim request = New PutObjectRequest With {
.BucketName = bucketName,
.Key = objectKey,
.InputStream = memoryStream,
.ContentType = "application/pdf"
}
Await _s3Client.PutObjectAsync(request)
End Using
End Function
End Class
End NamespaceBefore the try block, the file 'sample.pdf' is specified for reading from the IronPdfZip directory. The GetPdfFromS3Async method is then used to retrieve the PDF byte, which is passed to the LoadPdf method.
Increase Memory and Timeout
The amount of memory allocated in the Lambda function will vary based on the size of the documents being processed and the number of documents processed simultaneously. As a baseline, set the memory to 512 MB and the timeout to 300 seconds in aws-lambda-tools-defaults.json.
{
"function-memory-size": 512,
"function-timeout": 300
}
When the memory is insufficient, the program will throw the error: 'Runtime exited with error: signal: killed.' Increasing the memory size can resolve this issue. For more details, refer to the troubleshooting article: AWS Lambda - Runtime Exited Signal: Killed.
Publish
To publish in Visual Studio, right-click on the project and select 'Publish to AWS Lambda...', then configure the necessary settings. You can read more about publishing a Lambda on the AWS website.
Try It Out!
You can activate the Lambda function either through the Lambda console or through Visual Studio.
Frequently Asked Questions
How can I integrate IronOCR with AWS in a C# project?
To integrate IronOCR with AWS in a C# project, you need to set up an AWS Lambda function. Follow the step-by-step guide provided in the tutorial to configure IronOCR and read documents stored in an S3 bucket efficiently.
What are the prerequisites for using IronOCR on AWS Lambda?
Before using IronOCR on AWS Lambda, you need to have the AWS Toolkit for Visual Studio installed, an AWS Lambda project set up in .NET Core, and the AWSSDK.S3 package for managing S3 operations.
How do I handle OCR processing in a Lambda function using IronOCR?
In an AWS Lambda function, IronOCR can process images by retrieving them from an S3 bucket, using IronTesseract to read the content, and saving the results as searchable PDFs back to the S3 bucket.
Why is setting the temporary folder important when using IronOCR ZIP?
Setting the temporary folder path is crucial when using IronOCR ZIP because it requires write permissions to copy the runtime folder from the DLLs. This configuration allows IronOCR to function correctly within the Lambda environment.
What should I do if I encounter a 'signal: killed' error while using IronOCR on AWS Lambda?
If you encounter a 'Runtime exited with error: signal: killed' error, it may be due to insufficient memory allocation for your Lambda function. Increasing the memory size and timeout settings in the `aws-lambda-tools-defaults.json` file can resolve this issue.
How can I publish my AWS Lambda project using Visual Studio?
To publish an AWS Lambda project from Visual Studio, right-click on your project, select 'Publish to AWS Lambda...', and configure the necessary settings following the AWS documentation on publishing Lambda functions.
What is the recommended memory and timeout setting for processing large documents with IronOCR on AWS Lambda?
For processing large documents, it is recommended to allocate at least 512 MB of memory and set a timeout of 300 seconds to ensure the Lambda function runs smoothly without errors.
Can IronOCR process PDFs directly in AWS Lambda?
Yes, IronOCR can process PDFs directly in AWS Lambda by using the IronTesseract class to read PDFs loaded from an S3 bucket and return searchable PDFs back to the bucket.
How do I log OCR results in an AWS Lambda function using IronOCR?
In your AWS Lambda function, use the Lambda context's `Logger.LogLine` method to log OCR results. This allows you to track and verify the OCR output processed by IronOCR.
Is it necessary to install additional dependencies for IronOCR in .NET 8 when deploying to AWS Lambda?
No additional dependencies are required for utilizing the IronOCR library in a .NET 8 AWS Lambda project, aside from setting the correct paths and configuring necessary packages like AWSSDK.S3 for S3 operations.

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.