# FairScan: document scanning that never leaves the phone

> FairScan is a Kotlin Android scanner that detects documents with a custom segmentation model, corrects and enhances the image locally, and produces a PDF on device under the GPLv3 licence, with a deliberate refusal to offer manual adjustment controls.

**pynicolas/FairScan** — An Android app to scan your documents — simple and respectful

- Repository: https://github.com/pynicolas/FairScan
- Website: https://fairscan.org
- Stars: 1,014 · Forks: 65
- Language: Kotlin
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/pynicolas-fairscan

## FairScan is a scanner that refuses to send anything off the device

The project describes itself as an Android app to scan your documents, simple and respectful. The two words carry most of the design. Simple means the flow is scan, review if needed, save or share, with a clean interface and no manual adjustments. Respectful means the work happens on your phone: the README states that all document processing happens locally, with no cloud processing, no tracking, and no ads, and that the app asks for minimal permissions.

The audience is anyone who scans receipts, notes, or forms and does not want a copy of that paper sitting on a server. The distribution channels match that audience: the app is published on F-Droid and Google Play and also as GitHub releases, and the project hosts a website at fairscan.org with a blog section.

The compatibility requirement is modest, which is one of the more useful facts here. FairScan runs on any device with Android 8.0 or later and a camera. There is no separate hardware requirement and no server-side account.

What the README refuses is as informative as what it promises. There is a section titled what FairScan is not, and it lists fine-grained manual control over document processing, replicating all features found in other scanning apps, and optimizing for highly specific use cases at the expense of simplicity. That is a design commitment rather than a missing feature list.

## A custom LiteRT segmentation model finds the page in the photo

The first technical step is document detection, and it is the part that is specific to this project rather than borrowed. FairScan runs a custom-trained image segmentation model through LiteRT, formerly the TensorFlow Lite runtime, to decide where the page sits inside the picture the camera produced.

The model itself lives in a separate repository, fairscan-segmentation-model, and it is trained on a public dataset that is also published, fairscan-dataset. Both are linked from the README, which means the training input is inspectable rather than a proprietary blob.

The build pipeline fetches the model automatically. The README points at app/download-tflite.gradle.kts as the Gradle script that downloads the model during a build, so a contributor does not have to place the model file by hand.

This design carries the usual trade-off of an on-device model. Detection quality depends on a model trained on photographs of documents on surfaces, so unusual lighting, a very dark page, or a document photographed in a hand can push it off course. The project's own blog post on making document detection more reliable is linked from the README, which suggests the author treats detection as the part that keeps needing work rather than a solved step.

## OpenCV fixes the perspective and the lighting, PDFBox assembles the file

Once the page is located, the pipeline listed in the technical details section runs through OpenCV for perspective correction and image enhancement, then Tesseract for text recognition, and finally PDFBox-Android for PDF generation.

Perspective correction is what removes the keystone effect from a photo taken at an angle, which is the difference between a scan and a photograph of a page. The enhancement step is where a flat, dim photo becomes a legible page. Both happen in OpenCV, on the device, which is why the whole capture to PDF sequence needs no network connection.

The OCR stage is worth calling out because the feature list does not mention it. Text recognition with Tesseract is listed under technical details, so a scanned page can carry a text layer rather than only pixels. The README does not describe how that text layer is laid out on the page, or whether it is selectable and searchable in the produced PDF, so treat OCR quality and placement as something to verify on your own document types.

PDFBox-Android doing the assembly is what keeps the final step local as well. Nothing about the export requires an upload, which is the whole point of the privacy claim.

## Building the APK yourself with the Gradle wrapper

The README gives two build commands, and both go through the checked-in Gradle wrapper rather than a system Gradle installation. To produce an APK:

```bash
./gradlew clean check assembleRelease
```

To produce an Android App Bundle instead:

```bash
./gradlew clean check :app:bundleRelease
```

The check task runs first in both cases, so the static checks and tests are part of the build you ship rather than something you remember to run.

The repository layout explains how the pieces are separated. The top level holds app/, imageprocessing/, and evaluation/ alongside metadata/, which is where the store listing assets and screenshots live, given the metadata/en-US/images directory referenced by the README badges. settings.gradle.kts and build.gradle.kts define the modules, and gradle.properties holds the shared configuration.

Two things are worth knowing before you build. First, the model download happens inside the build, so a restricted or slow network will affect the first build rather than the runtime. Second, a release build assumes you can produce a signed artefact, since the assembleRelease and bundleRelease tasks produce packages meant for distribution.

## The experimental intent lets another app borrow the scanner

FairScan exposes a documented entry point for other applications. The intent action is org.fairscan.app.action.SCAN_TO_PDF, and it is an implicit intent that launches FairScan in a dedicated external mode.

The behaviour when started that way is spelled out. FairScan opens directly in scan mode, the user scans one or more pages, FairScan generates a single PDF, and that PDF is returned to the calling application as a URI with a limited lifetime. The calling application is expected to copy the content of the URI immediately, because FairScan deletes it later.

That last point is a real integration detail rather than a footnote. A URI that disappears means the caller has a short window to read the file, and any caller that assumes a permanent path will break. The README links a sample application, fairscan-intent-sample, for the pattern.

The warning is explicit as well. The feature is experimental, it is aimed at developers who want FairScan as a privacy-respecting scanning tool, and the intent contract and behaviour may change between versions with no backward compatibility guaranteed. Treat it as an integration point you can prototype against, not an API you can build a product feature on without accepting breakage.

## The alternative approach is a cloud scanner with editing handles

The realistic alternative is a hosted scanning service: the app uploads the photo, the server runs detection, enhancement, and OCR, and returns a PDF. That approach buys two things FairScan deliberately gives up.

The first is a richer editing surface. Cloud scanners typically let you crop, rotate, adjust contrast per page, and reorder, because the correction happens on a server you can re-run. FairScan's pipeline is one pass with no manual adjustments, and the README says outright that it is not intended to provide fine-grained manual control or to replicate all features found in other scanning apps.

The second is processing power and model quality. A server can run a heavier model and a larger OCR engine. FairScan is limited to what fits on a phone, which is why the segmentation model and the OpenCV stages are tuned to be fast rather than exhaustive.

The trade runs the other way on privacy and availability. The cloud path needs a working connection and copies every page to a third party, while FairScan keeps the images on the handset, works with the network off, and asks for minimal permissions. For a document you intend to email to a bank, that difference often matters more than the editing handles.

## GPLv3, Weblate translations, and releases every few weeks

The project is licensed under the GNU GPLv3, with the licence text in the LICENSE file and a LICENSE_HEADER file in the repository root for source headers. For an Android application distributed through app stores, GPLv3 means anyone who ships a modified build of FairScan has to publish that source. That has kept forks and modified versions in the open, and it is worth reading the licence before you base a product on it.

On activity, the last push was on 2026-10-10, and the release list shows v2.3.0 on 2026-09-20, v2.2.0 on 2026-07-19, and v2.1.0 on 2026-06-26. Releases land roughly every few weeks, which for an application means you can expect the interface and the model to change under you.

Translations are managed on Weblate, with the project set to require a 95 percent threshold for the language badge, and the README invites contributions there. The same page points to CONTRIBUTING.md for code contributions.

For a user, the upgrade path is the app store. For a developer embedding FairScan through the intent, the cost is higher, since the contract itself is marked unstable.

## Conclusion

Adopt FairScan if you scan paper on Android and want the pages never to leave the handset, and if you are willing to accept a fixed processing pipeline instead of a set of manual controls, with the project explicitly stating that it is not meant to replicate every feature of other scanning apps. Do not adopt it if you need manual crop and brightness tuning, a scan-to-PDF service other applications can call in a stable way, or output on a platform other than Android 8.0 and later. Verify three things on your own device first: that the segmentation model downloads through download-tflite.gradle.kts on your network, that the OCR output quality on Tesseract matches the accuracy your documents need, and that the PDFBox-Android output opens correctly in whatever reader you hand it to.

## FAQ

### Does FairScan upload my scanned documents to a server?

No. The README states that all document processing happens locally on your device, with no cloud processing, no tracking, and no ads, and that the app requests minimal permissions.

### How does FairScan detect a document in the photo?

It runs a custom-trained image segmentation model through LiteRT to locate the page. The model lives in the fairscan-segmentation-model repository and is trained on the public fairscan-dataset, and the build downloads it through app/download-tflite.gradle.kts.

### Can another Android app ask FairScan to scan a PDF for it?

Yes, through the experimental implicit intent org.fairscan.app.action.SCAN_TO_PDF. FairScan scans, generates a single PDF, and returns it as a URI with a limited lifetime that the caller should copy immediately, but the contract may change between versions.

### Does FairScan do OCR on my scanned pages?

The technical details list Tesseract for text recognition, so recognition runs locally as part of the pipeline. The README does not describe how the recognised text is laid out on the page in the resulting PDF.

### What Android version and licence does FairScan need?

It runs on any device with Android 8.0 or later that has a camera, and it is distributed under the GNU GPLv3 with the licence text in the LICENSE file.

## Sources

- [License: GPL-3.0](https://github.com/pynicolas/FairScan/blob/main/LICENSE)
- [Project website](https://fairscan.org)
- [pynicolas/FairScan on GitHub](https://github.com/pynicolas/FairScan)
- [README](https://github.com/pynicolas/FairScan/blob/main/README.md)
- [Releases](https://github.com/pynicolas/FairScan/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pynicolas-fairscan
