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.
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.
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
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
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
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
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
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
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
| Question | Other trackers | CycleVault |
|---|---|---|
| Does the screenshot leave my device? | Yes — uploaded to server | No — processed in browser |
| Who processes the image? | Company's cloud infrastructure | Your own device |
| Is the image deleted after? | You're trusting a promise | Cleared from memory — verifiable |
| Can I review before saving? | Usually auto-saved | Always — mandatory review step |
| Can I cancel and save nothing? | Data often already imported | Yes — at any point |
| Do you need to trust the company? | Yes | No — 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:
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.
- Low-resolution screenshots — if the image is small or blurry, text recognition accuracy drops. Take the screenshot at full resolution if possible.
- Unusual fonts or calendar layouts — most period apps use standard date formats, but decorative fonts can confuse OCR engines.
- Dark mode screenshots — light text on dark backgrounds can be harder to read. Try exporting a light-mode screenshot if available.
- Processing speed — on-device OCR uses your device's processor. On older devices this may take a few seconds longer than cloud processing.
- Symptoms and mood are not extracted — screenshot import reads dates only. For full history including symptoms and mood, use the CSV import.
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."
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 CycleVaultTesseract.js — open-source OCR, runs in-browser via WebAssembly. No server. No API key. Fully auditable.