Privacy & Engineering

How We Built Screenshot Import — Without Ever Seeing Your Screenshot

Most import tools send your image to a server. Ours doesn't. Here's exactly what happens — and why we built it this way.

📅 June 2025 6 min read 🔒 Privacy & Engineering

When you upload a screenshot to most apps, it travels to a server somewhere, gets processed by software running on someone else's computer, and — if you're lucky — gets deleted afterward. You're trusting a company's promise. With CycleVault's screenshot import, your image never goes anywhere. It's read entirely inside your browser, on your device, by open-source software. Here's how that actually works.

Why we built it differently

When we started thinking about data migration, the obvious approach was the one everyone else uses — upload the screenshot to a server, run OCR (optical character recognition) on it in the cloud, return the extracted dates, delete the image. Fast, accurate, easy to build.

We didn't build that. Here's why.

A screenshot of your period tracking calendar is one of the most intimate images a person can upload to a service. It contains months or years of health history — cycle dates, symptom logs, fertility windows, pregnancy attempts. Sending that to a server, even briefly, even with deletion promises, creates a window of exposure that contradicts everything CycleVault stands for.

"Your data never leaves your device" can't have an asterisk next to it. So we found a way to make import work without one.

The good news: we didn't have to compromise. Browser technology has advanced to the point where serious image processing can happen entirely on-device. Your browser is more capable than most people realise.

What other import tools do

To understand why on-device processing matters, it helps to see what the standard approach looks like:

✗ How most tools work
  • Image uploaded to company's server
  • Processed by cloud OCR service
  • Image passes through third-party infrastructure
  • Deletion depends on company's promise
  • Data exists outside your device, even briefly
  • You have no way to verify deletion
✓ How CycleVault works
  • Image loaded into browser memory only
  • Processed by Tesseract.js on your device
  • No network request is made at any point
  • Image cleared from memory after reading
  • Dates shown for your review before saving
  • You can cancel — nothing saved without approval

The difference isn't a matter of degree — it's architectural. One approach requires trusting a company. The other requires trusting only your own device.

The technology: Tesseract.js

The tool that makes this possible is called Tesseract.js — an open-source OCR (optical character recognition) engine that runs directly inside a web browser.

Tesseract was originally developed at HP Labs in the 1980s, later open-sourced by Google, and has been maintained by the open-source community ever since. It's one of the most widely used and audited OCR engines in the world. The JavaScript version — Tesseract.js — uses WebAssembly to run the same engine natively in any modern browser without any server involvement.

🧠 What is WebAssembly?

WebAssembly (WASM) is a technology that lets complex software — the kind normally requiring a server — run directly inside a browser at near-native speed. It's what makes Tesseract.js possible. Your browser downloads the OCR engine once, then runs it locally for image processing. No server, no cloud, no external dependency during processing.

Tesseract.js is open-source, meaning anyone can inspect exactly what it does. It is not our software — we don't control it and we didn't build it. That's actually a feature: open-source tools can be independently verified. You don't have to trust our word about what happens to your image. The code is public.

What happens when you upload a screenshot

Here is the exact sequence of events when you use CycleVault's screenshot import — nothing more, nothing less:

Step-by-step: on-device screenshot import

1

You select a screenshot from your device

The file is loaded into your browser's working memory using a standard browser file API. It does not leave your device at this point. No upload occurs.

✓ Still on your device

2

Tesseract.js reads the image locally

The OCR engine — already loaded in your browser — analyses the image pixel by pixel and extracts all text it finds. This processing happens entirely inside your browser tab using your device's processor. No network request is made.

✓ No network activity

3

The image is cleared from memory

The moment OCR finishes, the image is released from browser memory. It is not saved to localStorage, not cached, not retained in any form. What remains is only the plain text that Tesseract extracted — no image data.

✓ Screenshot gone before you see results

4

Dates are identified from the extracted text

CycleVault's code scans the extracted text for patterns that look like dates — in multiple formats and languages. It looks for context clues too: words like "period", "cycle", "flow", "started" that help identify which dates are cycle-related.

✓ Text only, no image

5

You review and decide what to save

Every extracted date is shown to you in a list. You check the ones you want, correct any errors, add missing dates, or cancel entirely. Nothing is saved to your CycleVault until you explicitly approve it.

✓ You are in full control

✓ The confirmation step is not optional

Every other import tool saves automatically and lets you fix errors after. CycleVault shows you the results first and saves nothing without your approval. You can uncheck individual dates, edit them, or cancel the whole import and walk away with nothing saved. This isn't just a privacy feature — it means your data stays accurate because you verified it.

The privacy guarantee in code

Privacy claims are easy to make. We want to show you the actual implementation principle — the moment the screenshot is cleared after OCR completes:

// Load image into browser memory for OCR
const imageData = loadImageFromFile(userSelectedFile);

// Supports 12+ languages — no network request made
// during this step. Language packs load locally in
// the browser, not from any server
const result = await Tesseract.recognize(imageData, 'eng+hun+deu+fra+spa+ita+nld+pol+swe+nor+dan+fin');
const extractedText = result.data.text;

// Screenshot cleared from memory immediately after OCR
// It is never written to localStorage, sessionStorage,
// or any persistent storage — only text remains
imageData = null;

// Parse dates from extracted text only
const foundDates = extractDatesFromText(extractedText);

// Show dates to user for review — nothing saved yet
showConfirmationScreen(foundDates);

The key line is imageData = null — the image reference is released immediately after OCR, before the confirmation screen ever appears. The screenshot is gone by the time you're reviewing your dates.

How this compares to other trackers

QuestionOther trackersCycleVault
Does the screenshot leave my device?Yes — uploaded to serverNo — processed in browser
Who processes the image?Company's cloud infrastructureYour own device
Is the image deleted after?You're trusting a promiseCleared from memory — verifiable
Can I review before saving?Usually auto-savedAlways — mandatory review step
Can I cancel and save nothing?Data often already importedYes — at any point
Do you need to trust the company?YesNo — verifiable in DevTools, on-device

Being honest about the limitations

On-device OCR is genuinely impressive, but it isn't magic. Tesseract.js is highly accurate on clear, standard screenshots — but there are cases where it struggles:

⚠ The most important limitation — calendar grids don't work

Screenshot import reads text characters. It cannot read visual elements like colored dots, icons, or shading. Most period app calendar views — including Flo's main calendar — show your cycle as colored circles, not written text. If you screenshot that view, OCR will find zero dates.

What to do instead: look for a Cycle history or Period log view in your app that lists entries as text. In Flo: go to Insights → Cycle history. Or use Settings → Import from Flo or Clue (CSV) for more complete results including symptoms and mood.

💡 This is why the review step exists

The confirmation screen isn't just a privacy feature — it's the quality control layer. Because OCR isn't perfect, you review every date before it enters your cycle history. Wrong date? Edit it. Missing one? Add it manually. Don't want to import at all? Cancel. The review step turns an imperfect technology into a reliable feature.

Why this matters beyond CycleVault

The approach we've described here — on-device processing using open-source tools, no server involvement, mandatory user review before data is committed — isn't just a CycleVault choice. It's a template for how health apps should handle sensitive data.

The industry assumption has been that useful features require data to leave the device. Screenshot import seemed like a feature that proved this — surely you need a server for OCR. Tesseract.js demonstrates that assumption is wrong. Meaningful processing can happen locally. Trust doesn't have to be delegated to infrastructure you can't see.

We hope other apps take notice. Your health data deserves better than "we promise we deleted it."

✓ Try it yourself

Don't screenshot your calendar grid — screenshot your text history view instead. In Flo: Insights → Cycle history. In Clue: Analysis → Period.

Then open CycleVault → Settings → Import from another app → Import from a text history view, and upload it.

For the most complete import including symptoms and mood, use Settings → Import from Flo or Clue (CSV) instead.

Try screenshot import

CSV import brings your full history from Flo or Clue including symptoms and mood. Screenshot import works for text-based history views — not calendar grids with colored dots.

Open CycleVault
🛠 Tech used

Tesseract.js — open-source OCR, runs in-browser via WebAssembly. No server. No API key. Fully auditable.

How to export and back up your CycleVault data

Why most period apps sell your health data — and what to do about it

Understanding the 4 phases of your cycle