diff --git a/NAPS2.Sdk.Samples/NAPS2.Sdk.Samples.csproj b/NAPS2.Sdk.Samples/NAPS2.Sdk.Samples.csproj
index af32efd666..e5f9bff28e 100644
--- a/NAPS2.Sdk.Samples/NAPS2.Sdk.Samples.csproj
+++ b/NAPS2.Sdk.Samples/NAPS2.Sdk.Samples.csproj
@@ -10,6 +10,7 @@
+
diff --git a/NAPS2.Sdk.Samples/NetworkSharingSample.cs b/NAPS2.Sdk.Samples/NetworkSharingSample.cs
new file mode 100644
index 0000000000..0ed5d9c048
--- /dev/null
+++ b/NAPS2.Sdk.Samples/NetworkSharingSample.cs
@@ -0,0 +1,56 @@
+using NAPS2.Escl.Server;
+using NAPS2.Images.Gdi;
+using NAPS2.Remoting.Server;
+using NAPS2.Scan;
+
+namespace NAPS2.Sdk.Samples;
+
+public class NetworkSharingSample
+{
+ public static async Task Server()
+ {
+ // NAPS2 can share scanners across the local network using the ESCL protocol with the NAPS2.Escl.Server package.
+ // On the server, you need to set up ScanServer with the device(s) to share.
+ // On the client, you just scan as usual using Driver.Escl.
+
+ using var scanningContext = new ScanningContext(new GdiImageContext());
+
+ // Get the device to share
+ var controller = new ScanController(scanningContext);
+ ScanDevice device = (await controller.GetDeviceList()).First();
+
+ // Set up the server (you'll need to reference NAPS2.Escl.Server to be able to create an EsclServer object).
+ using var scanServer = new ScanServer(scanningContext, new EsclServer());
+
+ // Register a device to be shared
+ scanServer.RegisterDevice(new SharedDevice
+ {
+ Name = device.Name,
+ Device = device,
+ Driver = Driver.Default
+ });
+
+ // Run the server until the user presses Enter
+ scanServer.Start();
+ Console.ReadLine();
+ scanServer.Stop();
+ }
+
+ public static async Task Client()
+ {
+ using var scanningContext = new ScanningContext(new GdiImageContext());
+ var controller = new ScanController(scanningContext);
+
+ // Find the shared device using Driver.Escl
+ ScanDevice device = (await controller.GetDeviceList(Driver.Escl)).First();
+
+ // Set up options using Driver.Escl
+ var options = new ScanOptions { Device = device, Driver = Driver.Escl };
+
+ // Do the scan
+ await foreach (var image in controller.Scan(options))
+ {
+ Console.WriteLine("Scanned a page!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/NAPS2.Sdk/README.md b/NAPS2.Sdk/README.md
index 7132a006c1..1ec150dee2 100644
--- a/NAPS2.Sdk/README.md
+++ b/NAPS2.Sdk/README.md
@@ -31,7 +31,9 @@ NAPS2.Sdk is modular, and depending on your needs you may have to reference a di
- **[NAPS2.Sane.Binaries](https://www.nuget.org/packages/NAPS2.Sane.Binaries/)**
- For [using SANE drivers]() on Mac. (Linux has them pre-installed, and Windows isn't supported.)
- **[NAPS2.Tesseract.Binaries](https://www.nuget.org/packages/NAPS2.Tesseract.Binaries/)**
- - For [running OCR](). (You can also use a separate Tesseract installation if you like.)
+ - For [running OCR](). (You can also use a separate Tesseract installation if you like.)
+- **[NAPS2.Escl.Server](https://www.nuget.org/packages/NAPS2.Tesseract.Binaries/)**
+ - For [sharing scanners](https://github.com/cyanfish/naps2/blob/master/NAPS2.Sdk.Samples/NetworkSharingSample.cs) across the local network.
## Usage