Time needed
240 minutes · 25 steps
What it takes
Nothing to install
What it costs
A free path exists
Last checked
2026-08-31
Careful with sensitive material
  • Grants and operations
  • Director or leadership
  • Transcribing testimonies and interviews
  • Grants and admin
  • Cleaning and analyzing data
  • Verifying images, video and claims
  • Protecting sensitive information
These are instructions, not case studies

A recipe tells you what to do. It is not a report of something that already happened somewhere else. Nothing here claims that any organisation did this. It is written for you to do now, and every step tells you how to check it worked.

A shoebox of Arabic paper receipts and a donor template whose columns match nothing you have. This recipe turns the box into a spreadsheet. Sort the box before you photograph anything: some of those receipts must never be uploaded.

The safety line

Three things leave your office, not one, and only the first is obvious. That is why step 2 sorts the box into two envelopes before anything is photographed.

Envelope B is anything that shows where a protected person was, or places a staff member at a specific address on a specific date: safe-house rent, a witness’s travel, a clinic, a lawyer’s office, a border crossing. It is also anything printed with a person’s name, phone number or ID number. Envelope B is typed by hand and never uploaded.

Do not write the word SENSITIVE on that envelope. An envelope marked SENSITIVE sitting on a desk has done a searcher’s sorting work for them. Mark the two envelopes A and B, and keep B wherever your organisation already keeps sensitive paper, not next to A on the desk.

On accuracy, and on Kurdish

Every number is checked by a human before it reaches a donor. On Sorani receipts, trust this recipe least of all: the one published score that looks good for Kurdish is recorded against an ISO code that does not distinguish Sorani from Kurmanji, so it is not evidence about Sorani at all.

What happens to your information

Never use this for

Never upload receipts that show where a protected person was, or that would place a staff member at a specific address on a specific date, safe-house rent, a witness's travel, a clinic, a lawyer's office, a border crossing, a hotel on the night of a meeting you would not describe publicly. Never upload a receipt that has a person's name, phone number or ID number printed on it. Those go into Envelope B in step 2 and get typed by hand in step 22. And do not write the word SENSITIVE on that envelope: an envelope marked SENSITIVE sitting on a desk has done a searcher's sorting work for them. Mark the two envelopes with something meaningless to an outsider, 'A' and 'B', and keep envelope B wherever your organisation already keeps sensitive paper, not next to envelope A on the desk.

What leaves your device

Whose law it lands under · The fully offline option

THREE THINGS LEAVE, NOT ONE, AND ONLY THE FIRST WAS OBVIOUS.

(1) THE UPLOAD. A photograph of each receipt you upload, which means the vendor's name, the vendor's address or branch, the date, the time of day, the line items, and the amount. That leaves your laptop or phone and goes to Google's servers. On the free tier it is used by Google to develop Google products and may be read by human reviewers. Your Google account identity, your IP address and your rough location travel with it as normal web traffic.

(2) THE PHONE BACKUP, WHICH HAPPENS BEFORE YOU EVER OPEN A BROWSER. On a default Android or iPhone, every photo you take is uploaded to Google Photos or iCloud within minutes. If you photograph the receipts and leave them in the gallery, the whole pile has already left the building under whatever terms that account carries, in a place none of this recipe's careful upload accounting covers. That is why step 1 of this recipe is switching backup off, before step 3 photographs anything.

(3) THE EXIF METADATA INSIDE EACH PHOTO. Phone photos carry precise GPS coordinates and a capture timestamp inside the image file itself. The central argument of this recipe is that a year of receipts becomes a map of your organisation's movements, EXIF turns that map from an inference somebody has to work out into machine-readable ground truth, and it rides along inside every file you upload. Step 1 turns location recording off; step 5 strips it from photos you have already taken.

Nothing else leaves. The CSV is produced in your browser or your spreadsheet and you save it locally.

TAKE THE AGGREGATE SERIOUSLY. One receipt is a boring piece of paper. Twelve months of receipts is a map: which neighbourhoods your staff were in, on which dates, at what hours, which hotels in which cities, which print shops, which fuel stations on which road, which restaurant on the day of a meeting. For an organisation under surveillance that dataset identifies your movements, your routine and, by inference, the people you met. It is more revealing than most of the documents you already treat as confidential. This is exactly why step 2 of this recipe is sorting the pile before you touch a computer, and why step 23 tells you where the finished file may and may not live.

Whose law it lands under

Google LLC, United States, for the main path, under the Google account you sign in with, and the human being who owns that account is the identified party in Google's records, not 'the organisation'. Under the unpaid Gemini API terms the content is used to develop Google products and may be seen by human reviewers; Google states it disconnects the data from your Google Account, API key and Cloud project before reviewers see it, but that is de-identification, not deletion.

DELETING THE PROMPT AFTERWARDS DOES NOT UNDO THIS. Step 16 tells you to delete the batch from AI Studio, and you should, because it stops colleagues on a shared account and anyone holding the laptop from browsing your receipts. But Google's terms do not state a retention period for Unpaid Services data and do not say whether content already used for product improvement, or already seen by a human reviewer, can be recalled. I read the document in this session and it is silent on both. Say it plainly to whoever signs off: once a receipt is submitted on the free tier, treat it as impossible to take back. That is the safe reading of a silent document, not a documented vendor policy.

If you switch to the paid tier the terms change materially: Google 'doesn't use your prompts (including associated system instructions, cached content, and files such as images, videos, or documents) or responses to improve our products', and logs them only for detecting and preventing violations of the Prohibited Use Policy.

FOR THE OTHER VENDORS I quote nothing, because this recipe's main path is Google and I did not open OpenAI's or Anthropic's data-usage pages in this session. Earlier versions of this recipe carried specific retention claims about both; they have been deleted rather than left standing on memory. If you move to another vendor, read that vendor's own data-usage page yourself before you upload anything.

The 2024 original of this recipe ran on Google Colab with a Google Drive folder of receipts; that would put your whole receipt archive in Google Drive, which is a bigger exposure than this recipe, not a smaller one, which is why the notebook is gone.

The fully offline option

There is a real offline route, and it is honestly not good enough for Arabic receipt totals. What exists: the Ollama desktop app for macOS and Windows lets a non-technical person drag an image into a chat window with no terminal and no internet; qwen3-vl:2b (1.9 GB), qwen3-vl:4b (3.3 GB) and glm-ocr (a 0.9B-parameter dedicated OCR model, 2.2 GB for the default tag and 1.6 GB for the q8_0 tag) all run on a normal laptop CPU. Sizes read from ollama.com in this session; check them again before you download, because tags change. Ollama's Linux download page offers only a shell install, no desktop app, on Linux this route is terminal-only.

What breaks: KITAB-Bench, the standing multi-domain Arabic OCR benchmark (arXiv:2502.14949, 8,809 samples across 9 major domains and 36 sub-domains), measured Character Error Rate on Arabic documents at 1.20 for Qwen2.5-VL-7B and 1.48 for Qwen2-VL-7B, a CER above 1.0 means the output is worse than useless. The dedicated OCR engines were also poor: Tesseract 0.54, EasyOCR 0.58, PaddleOCR 0.79, Surya 4.95. By comparison Gemini-2.0-Flash scored 0.13 and GPT-4o 0.31. (Gemini-2.0-Flash is now shut down and is listed under 'Previous models' on Google's docs. It is quoted here only as a benchmark datapoint, do not go looking for it in the model picker.) The paper's own summary is that modern vision-language models beat traditional OCR approaches on Arabic 'by an average of 60% in Character Error Rate'. Qwen3-VL and glm-ocr are newer than that benchmark and may be better, but nobody has published Arabic thermal-receipt numbers for them, so it is UNVERIFIED.

USE THE OFFLINE ROUTE FOR: receipts printed in Latin script with Western digits; building a private searchable index of your own archive; any work where a wrong number is embarrassing rather than disqualifying. DO NOT USE IT FOR: Arabic totals that go into a donor report. For sensitive Arabic receipts the genuinely local option is a human typing the number, which for the handful of sensitive receipts a small NGO has per month takes well under half an hour. That is step 22, and it is not a consolation prize, it is the correct answer.

What it costs

Paying for this from Iraq

Geo-blocking is NOT the problem. I opened all three vendors' own country lists in this session and Iraq is listed on every one: Google's Gemini API available-regions page, Anthropic's supported-countries page (under both the API and the Claude.ai sections), and OpenAI's supported-countries page. I have deliberately not quoted the surrounding alphabetical runs, a previous version of this recipe quoted a run that did not actually contain Iraq, which is exactly the kind of decorative detail that turns a true claim into a false citation. Open the three pages yourself if you need to prove availability to a colleague; they are in sources.

THE PROBLEM IS THE PAYMENT INSTRUMENT. All three vendors require an international credit or debit card, and Iraqi-issued cards (including Qi Card and Visa/Mastercard issued by Iraqi banks) are frequently declined by international SaaS billing. I could not verify this from any vendor's own documentation, no vendor publishes a list of card BINs it declines, so treat it as widely reported by Iraqi organisations rather than as documented vendor policy. Practical consequences: (1) The Google AI Studio free tier needs no card at all, which is why this recipe is built on it. (2) If you need a paid tier for the privacy terms, the realistic routes are a partner organisation abroad holding the billing account, or a prepaid international virtual card. (3) If a foreign colleague holds the API key, that colleague can see your usage and your billing records, and their jurisdiction now applies to your paperwork, decide that deliberately, do not let it happen by accident.

AND THE SAME IS TRUE OF THE FREE PATH, which is easy to miss: the person whose Google account you sign in with is personally the identified party in Google's records for every receipt uploaded. In a five-person NGO that is usually a shared office account, which means every colleague with the password can see the uploaded receipts in AI Studio. Decide whose account this is before step 8, and write the account name into the log in step 24.

ONE MORE PRACTICAL STALL: creating a NEW Google account often triggers SMS verification, and a fresh account created on a new device or over a VPN is more likely to be challenged. That is a stall that can end a session for someone working from a phone. Use an account that already exists and is already verified, and know whose phone number is on it.

The free path

If you pay

Yes, and it is the main path in this recipe. Google AI Studio (aistudio.google.com) has a free tier that needs a Google account and NO credit card at all. On Google's current pricing page, which I opened for this rewrite, Gemini 3.7 Flash, Gemini 3.6 Flash, Gemini 3.5 Flash, Gemini 3.5 Flash-Lite, Gemini 3.1 Flash-Lite, Gemini 2.5 Pro, Gemini 2.5 Flash and Gemini 2.5 Flash-Lite are all marked 'Free of charge' for free-tier input and output tokens. Google's own available-regions page lists Iraq for the Gemini API and Google AI Studio. I opened it and Iraq is there. That list changes; re-check it at https://ai.google.dev/gemini-api/docs/available-regions rather than trusting this sentence in a year. The spreadsheet is free too, and Google Sheets is the one that installs nothing at all, LibreOffice Calc is also free but is a substantial download, which is a real cost on a metered or slow connection (check the current size at libreoffice.org before you start), so this recipe names Sheets first.

THE PRICE OF FREE IS PRIVACY, AND GOOGLE SAYS SO IN WRITING. Google's Gemini API Additional Terms say for the unpaid tier: 'Google uses the content you submit to the Services and any generated responses to provide, improve, and develop Google products and services'; 'Human reviewers may read, annotate, and process your API input and output.'; and, the sentence you must read before you decide, 'Do not submit sensitive, confidential, or personal information to the Unpaid Services.' The paid tier says the opposite: 'Google doesn't use your prompts (including associated system instructions, cached content, and files such as images, videos, or documents) or responses to improve our products'. All four sentences read from https://ai.google.dev/gemini-api/terms in this session.

THE FREE DAILY CEILING IS UNPUBLISHED. Google's rate-limits page no longer prints free-tier requests-per-minute or requests-per-day numbers; it tells you to 'View your active rate limits in AI Studio'. So work in batches of ten receipts, save each batch before starting the next, and stop if you get a quota error. Free is only free if the batch completes, so do not plan on finishing a whole month in one sitting.

Fully offline alternative also free: Ollama plus a small vision model, no account and no internet, but see the language warning. It does not work well enough on Arabic receipt totals.

If you pay

DO NOT BUDGET FROM A NUMBER IN THIS DOCUMENT. Every per-token price and every worked monthly estimate that used to sit here has been deleted, because prices move, promotional rates expire, and this page will be read for a year after the conference. Read the current rate yourself: Google https://ai.google.dev/gemini-api/docs/pricing, Anthropic https://www.anthropic.com/pricing, OpenAI https://openai.com/api/pricing. Watch for promotional rates with an expiry date printed beside them, Google's pricing page marks some rates that way, so the figure you see today may not be the figure you pay next year.

What is worth saying without a number: for a small NGO transcribing a few hundred receipts a month, image-in and short-text-out is one of the cheapest things you can do with any of these APIs, and the monthly bill is not what stops people. THE REAL BLOCKER IS NOT THE PRICE, IT IS THE CARD. Do not budget around the dollars; budget around whether you can pay at all, see the payment note.

Before you start

  • A phone with a camera, or a scanner. Nothing more for the main path.
  • A Google account that ALREADY EXISTS and is already phone-verified, and a decision about whose it is. Creating a fresh Google account often triggers SMS verification, and a new account made on a new device or over a VPN is more likely to be challenged. That stall can end your session. The person who owns this account is the identified party in Google's records for every receipt you upload, and on a shared office account every colleague with the password can see them. Decide this before you start; you will write it into the log in step 24. No credit card is needed and none will be asked for.
  • A web browser and an internet connection good enough to upload phone photos. One photo per receipt, so ten uploads per batch.
  • A spreadsheet. GOOGLE SHEETS is the genuinely no-install option: it is free, it runs in the browser you already have open, and it is what this recipe assumes. LibreOffice Calc (free, offline, libreoffice.org) also works and is better if you do not want the file in a cloud at all, but it is a substantial download, so check its size and plan for that on a slow or metered connection. Microsoft Excel works too if you already have it.
  • Two paper envelopes and a pen. This is not a joke; step 2 depends on them.
  • A calculator, or the calculator app on your phone, for the reconciliation in step 20.
  • Optional, only for the offline lane in step 25: a laptop with enough memory to run a small vision model, 8 GB of RAM is a realistic floor, and that figure is my judgement rather than a vendor specification, plus free disk for the model download. The current download sizes are printed on each model's page at ollama.com; check there rather than trusting a number here. Windows or macOS for the drag-and-drop app; Linux users need the terminal.

Which machines this works on

TIME FIRST, BECAUSE THE OLD ESTIMATE WAS WRONG. These are estimates, not measurements. Expect roughly an hour and a half to get through your first batch of ten receipts, start to finish, including reading this. A full month of about forty receipts is closer to half a day. You do NOT have to do it in one sitting: each batch of ten is a complete, saved, verified unit of work, and you can stop after any batch and resume next week. That also protects you against the free-tier daily ceiling, which Google no longer publishes. Its rate-limits page carries no free-tier requests-per-minute or requests-per-day figures and tells you to view your active rate limits in AI Studio instead. If you hit a quota error, the batches you already saved are still good.

WINDOWS (the majority of this room). Everything on the main path works: browser, Notepad, and either Google Sheets in the browser or Excel. Three Windows-specific traps, all covered in the steps. (1) Do NOT open the .csv by double-clicking it in Excel, Windows Excel opens it in the local codepage and the Arabic turns into question marks. Use Data > From Text/CSV and set File Origin to 65001: Unicode (UTF-8). (2) Notepad's Save-as dialog has an Encoding dropdown that must be set to UTF-8 before you press Save. (3) A .csv file cannot hold a password, step 23 tells you what to do instead, and this is the one place a reader used to hit a dead end. The Ollama offline lane in step 25 has a Windows desktop app with drag-and-drop, so no terminal is needed there either.

macOS. Same main path. TextEdit must be switched to plain text (Format > Make Plain Text) before you can save a .csv. Numbers.app is not covered here, use Google Sheets or LibreOffice Calc. The Ollama desktop app also exists for macOS with drag-and-drop.

LINUX. Same main path with any text editor and LibreOffice Calc. Ollama's own Linux download page offers only a shell install, no desktop package, so the offline lane in step 25 is terminal-only on Linux. That is the one place in this recipe where the platform changes what you have to do, and it is an optional step.

PLATFORM-LIMITED ROUTES, so you know before you start: nothing on the main path is platform-limited. The only platform-limited thing here is the optional offline lane's drag-and-drop app (Windows and macOS only).

OLD LAPTOPS AND SMALL SCREENS. The main path is a browser tab and a spreadsheet; an 8 GB laptop is fine and so is a phone for the photographing. The optional offline lane in step 25 needs room for a multi-gigabyte model download and will be slow.

The steps

  1. Step 1 / 25All platforms

    BEFORE YOU PHOTOGRAPH ANYTHING: turn off automatic photo backup, and turn off location recording in the camera. If you skip this, the whole pile of receipts is uploaded to Google Photos or iCloud, with GPS coordinates, within minutes of you taking the pictures, before you have decided anything.

    Check it worked

    Take one test photo of anything. Wait two minutes. On Android, open the Google Photos app, tap your profile picture, and confirm it says backup is off. On iPhone, open Settings > [your name] > iCloud > Photos and confirm the sync toggle is off. Then open the test photo's details (swipe up on iPhone, or tap the 'i' / three dots on Android) and confirm there is NO map and no location shown. If you see a map, location is still on.

    Note

    ANDROID: Google Photos app > profile picture (top right) > Photos settings > Backup > turn Backup OFF. Then open the Camera app > Settings (gear) > turn 'Location' or 'Save location' OFF. IPHONE: Settings > [your name] > iCloud > Photos > turn 'Sync this iPhone' OFF. Then Settings > Privacy & Security > Location Services > Camera > set to 'Never'. Menu wording moves between versions, if you cannot find the exact item, search the phone's Settings app for 'backup' and for 'location'. You can turn both back on when you are finished; put a reminder in your phone so you actually do. If you are using a scanner attached to a computer instead of a phone, none of this applies, a scanner records no GPS and does not back anything up.

  2. Step 2 / 25All platforms

    Before you touch a computer, sort the whole pile of receipts into two envelopes. Write only the letter A on one and only the letter B on the other. While you sort, put a tick in one of two columns on a scrap of paper for each receipt in envelope A: dinars or dollars.

    Check it worked

    Every receipt from the pile is now inside one of the two envelopes and none are loose on the desk. Your scrap of paper shows two counts for envelope A that add up to the number of receipts in envelope A. Envelope B is not on the desk any more. It is wherever your organisation keeps sensitive paper.

    Note

    ENVELOPE A (ordinary) means the receipt would tell a stranger nothing they could use: office paper, printer toner, bottled water, generic fuel, a taxi with no destination on it, the electricity bill. ENVELOPE B (sensitive) means the receipt places a specific person somewhere specific at a specific time, or carries a name, phone number or ID number: hotels, clinics, lawyers, a restaurant on the day of a meeting you would not describe publicly, rent, anything connected to a protected person or a witness. When you hesitate, the receipt goes in B. Envelope B never gets photographed and never gets uploaded. You will type those by hand in step 22.

    WHY 'A' AND 'B' AND NOT 'SENSITIVE': an envelope with SENSITIVE written on it, sitting on a desk, has done a searcher's sorting for them. Label it neutrally and store envelope B wherever you already store sensitive paper, not beside envelope A.

    WHY THE CURRENCY TALLY: in Erbil and Baghdad a normal month's receipts contain both dinars and dollars, hotels, generators, rent and most procurement are often priced in USD. This recipe keeps the two currencies in two separate columns and reconciles them separately, because adding a 500 dollar hotel to a 3,000 dinar taxi produces a number that means nothing. Knowing the two counts up front lets you check the spreadsheet against reality in step 18.

    This one step is what makes the rest of the recipe safe enough to use, and it is quick, a month of receipts sorts in the time it takes to drink a tea. Also write the date range of the batch on the outside of envelope A.

  3. Step 3 / 25All platforms

    Photograph only the receipts in envelope A. One receipt per photo. Do not photograph two receipts side by side.

    Check it worked

    Scroll through the photos you just took. Count them. The count must equal the number of receipts in envelope A. Open the three worst-looking photos at full zoom and read the total on each with your own eyes. If YOU cannot read the total on the screen, no model will read it either, retake that photo now, while the paper is still in your hand.

    Note

    Lay the receipt flat on a dark surface, a dark desk, a closed notebook, a black bag. A dark background makes the paper edge obvious to the model. Use daylight coming from the side, from a window, and TURN THE FLASH OFF: thermal receipt paper is glossy and a flash burns a white stripe straight across the total. Hold the phone directly above, not at an angle, and fill the frame with the receipt, but include the very top and the very bottom, because the vendor name is at the top and the total is usually at the bottom. If a receipt is longer than the frame, take two overlapping photos and note in your own records that it is two files. Thermal receipts fade with heat and time, so photograph them the week you get them; if one has already faded, tilt it slightly under the light until the ghost of the printing catches the sheen, and photograph it there.

  4. Step 4 / 25All platforms

    Copy the photos from the phone into ONE folder on the computer. Do not rename them.

    Check it worked

    Open the folder and set it to show file names (in Windows File Explorer, View > Details; on macOS Finder, View > as List). Count the files: the count must equal the number of receipts in envelope A. You should be able to read each file's name, for example IMG_2041.jpg.

    Note

    The filenames your phone produced (IMG_2041.jpg and so on) are your link back to the paper, and you will need that link in steps 12, 19, 21 and 22 when you check a suspicious row.

    ANDROID ON WINDOWS: connect the phone by cable, unlock it, and on the phone choose the USB option for transferring files. Open File Explorer, open the phone > Internal storage > DCIM > Camera, select the photos, copy, and paste into a new folder such as Documents\receipts-2026-08.

    IPHONE ON WINDOWS (this used to be missing from the recipe): connect the iPhone by cable, unlock it, and tap Trust on the phone when it asks. The iPhone then appears in File Explorer under This PC as a device, open it > Internal Storage > DCIM, where the photos sit in folders named like 100APPLE. Copy them out into your new folder. If the phone shows no folders at all, it is still locked or you did not tap Trust; unplug, unlock, and try again.

    macOS: connect an iPhone and open the Photos app or Image Capture, select the photos, and export them into a new folder.

    If you have no cable, emailing them to yourself works but is another copy in another mailbox, prefer the cable. Sort the folder by name so the order is stable; that order is the order you will upload in.

  5. Step 5 / 25Windows

    Remove the location data from the copies in that folder. Do this even if you turned location off in step 1, because photos taken before today still carry it.

    Check it worked

    Right-click one of the photos, choose Properties, open the Details tab, and scroll to the GPS section. There must be no latitude and no longitude. If the GPS section has disappeared entirely, that is the correct result.

    Note

    WINDOWS: open the folder, select all the photos (Ctrl+A), right-click > Properties > Details tab > click 'Remove Properties and Personal Information' at the bottom. In the dialog that opens, choose the second option, 'Remove the following properties from this file:', then click 'Select All', then OK. This edits the files in place and KEEPS their filenames, which matters for step 12. Do NOT choose the first option ('Create a copy with all possible properties removed'). That makes a second set of files with ' - Copy' in the names and leaves the originals untouched.

  6. Step 6 / 25macOS

    Remove the location data from the copies in that folder.

    Check it worked

    Open one photo in Preview, then Tools > Show Inspector > the (i) tab. There must be no GPS tab. If a GPS tab with coordinates is still there, the export did not strip it, redo the export with the Location option switched off.

    Note

    macOS: the reliable route is to strip it at export time rather than after the fact. On the IPHONE, before copying anything across: open Photos, select the receipt photos, tap Share, then at the top of the share sheet tap 'Options', turn 'Location' OFF, and then save or send them. On the MAC, if the photos are already in the Photos app: select them, then File > Export > Export Unmodified Original, and in the export dialog untick 'Location Information' if offered. If you have already copied files across without stripping, the simplest honest fix is to redo the export with Location off.

  7. Step 7 / 25Linux

    Remove the location data from the copies in that folder.

    Copy this exactly

    exiftool -all= -overwrite_original *.jpg

    Check it worked

    Run: exiftool -gps:all IMG_2041.jpg, replace IMG_2041.jpg with one of your filenames. It must print nothing at all. If it prints a latitude, the strip did not run.

    Note

    LINUX: exiftool is not installed by default. On Debian and Ubuntu the package is libimage-exiftool-perl (name confirmed against the Debian package index in this session), so: sudo apt install libimage-exiftool-perl. On Fedora it is normally perl-Image-ExifTool, if that name has moved, find it with: dnf search exiftool. Then open a terminal, change into the folder with your photos (cd ~/Documents/receipts-2026-08), and run the command above. The -overwrite_original flag edits the files in place and keeps their filenames, which matters for step 12. If your photos are .jpeg or .png rather than .jpg, change the pattern to match.

  8. Step 8 / 25All platforms

    Open a browser and go to Google AI Studio. Sign in with the account you decided on in the prerequisites.

    Copy this exactly

    https://aistudio.google.com

    Check it worked

    You can see a chat box you can type into, and your account's initial or profile picture in the corner. Click it and confirm it is the account you intended, not a personal one you happened to be signed into. If a 'choose an account' screen appears, choose deliberately.

    Note

    This works from Iraq, Google's own available-regions page lists Iraq for the Gemini API and Google AI Studio, and I opened that page while writing this. Availability lists change, so if you want to check it for yourself before a trip or a grant report, the page is https://ai.google.dev/gemini-api/docs/available-regions. It is free and it will not ask for a credit card. If you are asked to accept terms, that is normal; those are the terms quoted in step 10, and step 10 is where you actually decide about them.

  9. Step 9 / 25All platforms

    In the model selector at the top or side of the screen, choose Gemini 3.7 Flash.

    Copy this exactly

    gemini-3.7-flash

    Check it worked

    The model name shown next to the chat box reads Gemini 3.7 Flash (or whichever Flash model you picked). If it still says a Lite model or a Pro model, change it now. You will not be able to tell later which model produced a row.

    Note

    Gemini 3.7 Flash is on Google's free tier: I opened the pricing page in this session and its free-tier input and output are both marked 'Free of charge'. If you cannot find it, gemini-3.6-flash, gemini-3.5-flash and gemini-2.5-flash were also marked free of charge on that same page and will work. Model names turn over fast, if none of those are in your picker, open https://ai.google.dev/gemini-api/docs/pricing and choose whichever full Flash model is marked free today. Avoid the Lite models for this job. Receipts are a hard vision task and the small models drop digits. If AI Studio shows a 'thinking' or 'reasoning' setting, leave it at its default; you want the model to look twice at a blurry digit.

    READ THIS BEFORE YOU TRUST THE OUTPUT, because it is the honest limit of the whole recipe: nobody has published Arabic OCR accuracy figures for the current generation of frontier models. The only published Arabic number in this recipe is a Character Error Rate of 0.13 for Gemini-2.0-Flash, a model Google has now shut down, measured on clean printed documents, not on faded thermal receipts, in a benchmark whose authors list numeral recognition errors as a standing limitation of Arabic OCR. Today's model is probably better than that. I cannot show you by how much, and neither can anyone else. That is why steps 18 to 21 exist and are not optional. And there is no published evidence at all for Kurdish Sorani.

  10. Step 10 / 25All platforms

    STOP AND DECIDE. Read what Google says about the free tier, including the sentence that tells you not to do this, and decide, with a named person's sign-off, whether envelope A is acceptable to send anyway.

    Check it worked

    You have a name written down: the person in your organisation who decided this is acceptable, and the date. If you cannot write a name, you have not made the decision yet and should not upload.

    Note

    Google's Gemini API Additional Terms say three things about the unpaid tier. All three, quoted from https://ai.google.dev/gemini-api/terms, which I opened while writing this:

    'Google uses the content you submit to the Services and any generated responses to provide, improve, and develop Google products and services.'

    'Human reviewers may read, annotate, and process your API input and output.'

    'Do not submit sensitive, confidential, or personal information to the Unpaid Services.'

    That third sentence is Google's own written instruction, and an NGO's financial records are confidential business information under any ordinary reading. If you proceed, you are proceeding against it. Do not let anyone tell you otherwise later. Read the page yourself before you sign anything off, terms change, and this is the one page in the recipe worth opening every time.

    HERE IS THE ARGUMENT FOR PROCEEDING, and you should test it against your own situation rather than accept it: envelope A was deliberately built to contain only receipts that reveal nothing about a person, toner, water, generic fuel, the electricity bill. Everything that could place a person anywhere is in envelope B and will never be uploaded. The residual exposure is that Google, and possibly a human reviewer, learns which shop your office buys paper from. For most organisations that sits inside their risk tolerance. For an organisation already under targeted surveillance, or one whose donor agreement forbids third-party disclosure of financial records, it does not.

    AND YOU SHOULD ASSUME IT CANNOT BE UNDONE. Step 16 has you delete the batch from AI Studio, and you should, because it stops colleagues on a shared account seeing it. But Google's terms state no retention period for Unpaid Services data and say nothing about recalling content already used for product improvement or already seen by a reviewer. I read the document looking for it; it is silent. Treat free-tier submission as irreversible. That is the safe reading of a silent document, not a documented policy.

    IF THE ANSWER IS NO, you have two honest options and no third. Move to Google's paid tier, where the terms say Google 'doesn't use your prompts (including associated system instructions, cached content, and files such as images, videos, or documents) or responses to improve our products', see the payment note about Iraqi cards, which is the real obstacle. Or go to the offline lane in step 25 and accept accuracy that does not work for Arabic totals. There is no option where you get free, private and accurate at once. Say that plainly to whoever signs off, and write their name and the date down now. It goes into the log in step 24.

  11. Step 11 / 25All platforms

    Upload exactly ten receipt photos into the chat, using the image or file button. Ten, not forty. Upload them in filename order and remember that order.

    Check it worked

    Count the thumbnails in the message box before you send anything. There must be exactly ten (or, for your last batch, however many are left). If AI Studio shows fewer thumbnails than you selected, one upload failed silently, remove them all and re-add.

    Note

    Ten at a time for three reasons: a free-tier quota error halfway through a batch of forty loses the whole batch; long batches are where models silently skip a receipt; and ten rows is a quantity a human will actually check. If you get a quota or rate-limit message, wait a few minutes and try again, Google no longer publishes a free-tier daily limit in its documentation and tells you to view your active rate limits in AI Studio, so the real ceiling is unverified. Whatever you have already saved stays saved.

  12. Step 12 / 25All platforms

    In the message box, below the images, first type a numbered list of the filenames in the exact order you uploaded them, and then paste the prompt below it, exactly as written. Do not shorten the prompt. Every rule in it exists because of a specific way this goes wrong.

    Copy this exactly

    Here are the filenames of the images I uploaded, in the same order I uploaded them:
    1. IMG_2041.jpg
    2. IMG_2042.jpg
    3. IMG_2043.jpg
    4. IMG_2044.jpg
    5. IMG_2045.jpg
    6. IMG_2046.jpg
    7. IMG_2047.jpg
    8. IMG_2048.jpg
    9. IMG_2049.jpg
    10. IMG_2050.jpg
    
    You are transcribing photographed receipts for an accounting record. Accuracy matters more than completeness.
    
    For each receipt image I gave you, output ONE row of CSV. Do not merge receipts. Do not invent data.
    
    HOW MANY ROWS: output exactly one row per filename in my numbered list above, plus the header row. Count the entries in that list and use that count. Do not assume the count is ten. If the number of images I attached does not equal the number of filenames in my list, do not guess, say so in one sentence and stop.
    
    Columns, in this exact order:
    file,date_iso,vendor_arabic,vendor_latin,total_as_printed,currency,amount_iqd,amount_usd_cents,confidence,notes
    
    FORMAT RULES
    F1. Wrap EVERY field in double quotes, including the header row and including empty fields. This is not optional: a comma inside a vendor name or inside a note would otherwise break the row and shift every column after it.
    F2. Never put a double quote character, and never put a line break, inside a field.
    F3. Put the whole answer inside ONE fenced code block, opened and closed with three backticks, and write nothing outside it. No sentence before it, no sentence after it.
    
    COLUMN RULES
    1. file: the filename from my numbered list above that corresponds to this image. Image 1 gets filename 1, image 2 gets filename 2, and so on in order. Never write "image 1" or "unknown" here.
    2. date_iso: the date printed on the receipt, as YYYY-MM-DD. If the year is not printed, write UNKNOWN. Never infer the year from context.
    3. vendor_arabic: the business name exactly as printed, in Arabic or Kurdish script. If it is not printed, write UNKNOWN. Do not correct the spelling. Do not substitute a business you think it resembles.
    4. vendor_latin: a plain transliteration of that name. If you are guessing, write UNKNOWN.
    5. total_as_printed: a single # character, then the grand total copied character for character exactly as it appears on the paper. Keep the original digits, whether they are Arabic-Indic (٠١٢٣٤٥٦٧٨٩), Extended Arabic-Indic (۰۱۲۳۴۵۶۷۸۹) or Western (0123456789), and keep any separator (٫ ٬ , .) exactly where it appears. Do not convert. Do not tidy. Do not add or remove a separator. The leading # is a marker I need; everything after it must be an exact copy.
    6. currency: IQD, USD, or UNKNOWN. Decide only from what is printed on the receipt: $ or USD or دولار means USD; د.ع or IQD or دينار means IQD. If no currency is printed anywhere on the receipt, write UNKNOWN and say so in notes. Never assume a currency from the size of the number.
    7. amount_iqd: fill this ONLY if currency is IQD; otherwise leave it empty. Write the amount in Western digits 0-9 as a WHOLE NUMBER of dinars with NO decimal point, NO comma and NO separator of any kind. Receipt amounts in Iraqi dinars are whole dinars; fils are not used in practice. Example: a receipt printed ٢٥٬٠٠٠ is twenty-five thousand dinars, so write 25000, not 25.000, not 25,000, and not 25. If the separator printed on the receipt is ٫ (ARABIC DECIMAL SEPARATOR, U+066B) rather than ٬ (ARABIC THOUSANDS SEPARATOR, U+066C), still read it as a thousands mark, but set confidence to MEDIUM and write in notes: decimal separator used as thousands mark.
    8. amount_usd_cents: fill this ONLY if currency is USD; otherwise leave it empty. Write the amount as a WHOLE NUMBER OF CENTS, in Western digits, with NO decimal point and NO separator of any kind. Examples: $25.00 is 2500. $12.50 is 1250. $1,200 is 120000. $7 is 700. Never write 25, and never write 25.00, in this column.
    9. If currency is UNKNOWN, leave BOTH amount columns empty and set confidence to LOW.
    10. confidence: HIGH only if every single digit of the total AND the printed currency marking are sharp and unambiguous. MEDIUM if you had to reason about any digit or about the currency. LOW if the paper is faded, creased, glared, cut off, or the total is printed twice.
    11. notes: name the specific problem in a few words, for example: total partly faded; or: two totals printed; took the lower one; or: third digit could be 5 or 0. If there is no problem, write OK.
    
    NEVER GUESS A DIGIT. If any digit of the total is unreadable, leave BOTH amount columns empty, set confidence to LOW, and write UNREADABLE in notes together with which digit is unreadable.

    Check it worked

    Before you press send: the filenames you typed must be the filenames actually in the message, in the same order as the thumbnails, and there must be exactly as many numbered lines as there are thumbnails. Read them once against the folder listing. This one-minute check is what makes every later row-to-receipt lookup possible.

    Note

    REPLACE THE EXAMPLE FILENAMES with your own, and DELETE ANY LINES YOU DO NOT NEED. This matters on your last batch of the month, which is almost never exactly ten: if the pile leaves you seven receipts, your numbered list must have seven lines and only seven. The prompt now takes its row count from that list rather than from a hardcoded ten, so a short final batch produces seven rows, an earlier version of this recipe said 'output exactly 10 rows' and would push a model to pad a short batch with invented ones.

    Faster routes for the filenames if you want them, WINDOWS: select the photos in File Explorer, hold Shift, right-click, choose 'Copy as path', paste into the AI Studio message box, then delete the folder part and the quotes. macOS: select the photos in Finder, right-click, hold down the Option key so 'Copy' becomes 'Copy items as Pathnames', then paste. LINUX: in the folder, run ls -1 in a terminal.

    WHY THE FILENAME LIST EXISTS AT ALL: AI Studio hands the model the image data, not your phone's filename. Without this list the file column comes back as 'image 1' to 'image 10' and every row-to-receipt lookup in steps 19, 21 and 22 falls back to whatever you can remember about upload order, which is exactly the thing you will not remember in three weeks when a donor queries a number.

    WHY RULE 5 AND RULES 7/8 TOGETHER ARE THE SAFETY MECHANISM OF THIS WHOLE RECIPE: they force the model to show its working, so a human can compare the printed number against the converted number without going back to the paper. The leading # in rule 5 is a fence: it stops your spreadsheet from silently 'helpfully' turning a printed 25,000 into a number and destroying the evidence you are about to check.

    WHY THERE ARE TWO AMOUNT COLUMNS: in Erbil and Baghdad the pile contains both dinars and dollars, and a single 'total' column makes the check in step 20 impossible to pass even when every transcription is correct. Two columns, each a whole number with no separators, means every locale and every spreadsheet reads them identically and you reconcile each currency against its own calculator total.

    WHY CENTS RATHER THAN DOLLARS: a whole number with no separator cannot be misread by any spreadsheet in any language setting. '25.00' can be, in some language settings a full stop is a thousands mark, and $25.00 silently becomes 2500 dollars. Cents are slightly awkward to read and completely immune to that.

    WHY RULE 7 NAMES BOTH SEPARATORS: ٫ and ٬ are two different Unicode characters with two different meanings, U+066B is the decimal separator, U+066C is the thousands separator, and Iraqi thermal printers do not always use the right one. ISO 4217 formally assigns the Iraqi dinar three decimal places even though fils are not used, so a model that 'knows' about IQD can read ٢٥٫٠٠٠ as twenty-five dinars. Rule 7 forbids that reading and makes the model flag it.

    WHY RULE F3 ASKS FOR A CODE BLOCK: AI Studio renders the reply as formatted text. Inside a fenced block you get a one-click copy button and the exact characters. Selecting rendered text with the mouse can silently merge or rewrap lines, which is precisely the 'a receipt vanishes' failure this recipe spends four steps guarding against.

  13. Step 13 / 25All platforms

    Read the answer on screen and check it before you copy it. It should be a single grey code block, starting with a quoted header line, with one row per photo you uploaded, and the file column should show YOUR filenames.

    Check it worked

    Three things must all be true. (a) The number of data rows after the header equals the number of photos you uploaded in this batch, count them with your finger, and remember that a short final batch should produce a short answer, not ten rows. (b) The first column shows IMG_2041.jpg and so on, not 'image 1'. (c) Every field on every row is wrapped in double quotes. If any of the three is wrong, do not paste it into a spreadsheet, fix it now.

    Note

    IF THERE ARE FEWER ROWS THAN PHOTOS: reply in the same chat with 'You gave me N rows for M images. Output all M rows, one per image, in the same format.' A missing row is the single most common silent failure, and it means a receipt vanishes from your accounts entirely with no error message anywhere.

    IF THERE ARE MORE ROWS THAN PHOTOS: the model has invented one. Reply with 'I uploaded M images and listed M filenames. Output exactly M rows, one per filename, and nothing else.' This is the failure a short final batch provokes.

    IF THE FILE COLUMN SAYS 'image 1': the filename list did not reach the model. Reply with 'Redo the file column using the numbered filename list I gave you: image 1 is IMG_2041.jpg, image 2 is IMG_2042.jpg' and so on.

    IF THE FIELDS ARE NOT QUOTED: reply with 'Output it again with every field wrapped in double quotes, including the header row.' Unquoted output will look fine and then shift half your columns sideways the moment one vendor name contains a comma.

    IF THE MODEL WROTE A SENTENCE BEFORE OR AFTER THE BLOCK: ignore the sentence and copy only the block. Use the copy button in the corner of the code block rather than selecting with the mouse.

  14. Step 14 / 25All platforms

    Paste the copied text into a plain text editor and save it as a file ending in .csv, with the encoding set to UTF-8. If the paste starts or ends with three backticks, delete those lines.

    Copy this exactly

    receipts-batch-01.csv

    Check it worked

    Close the file and open it again in the same editor. The first line must begin with "file","date_iso", with the quotes. The Arabic vendor names must still be Arabic letters, not question marks or boxes. If you see ????? or ا, the encoding was wrong: close without saving, and redo the save with UTF-8 selected.

    Note

    WINDOWS: open Notepad, paste, then File > Save as. In the Save dialog, change 'Save as type' to 'All Files', type the name receipts-batch-01.csv, and. This is the part people miss, set the 'Encoding' dropdown at the bottom to UTF-8 BEFORE clicking Save. macOS: open TextEdit, and FIRST choose Format > Make Plain Text, then paste, then File > Save, name it receipts-batch-01.csv, and make sure 'Plain Text Encoding' is Unicode (UTF-8). LINUX: gedit, Text Editor or Kate; choose UTF-8 in the save dialog if offered (it is usually the default). If you skip the UTF-8 part, the Arabic vendor names and the Arabic digits turn into rows of question marks and you will have to redo the whole batch.

  15. Step 15 / 25All platforms

    Open that .csv in your spreadsheet, choosing UTF-8 when it asks. Do not force any column to Text, the # marker already protects the evidence, and forcing columns to Text is what makes the check in step 20 return zero.

    Check it worked

    Look at the sheet. Column E (total_as_printed) must still show the Arabic characters after a #, for example #٢٥٬٠٠٠, left-aligned like text. Columns G and H (amount_iqd, amount_usd_cents) must show plain numbers RIGHT-ALIGNED against the right edge of the cell. Right-aligned means the spreadsheet read them as numbers, which is what step 20 needs. If G and H are left-aligned, they came in as text and every sum will silently be zero, redo the import following the note.

    Note

    The columns land in this order and these letters, and every later step uses these letters: A file, B date_iso, C vendor_arabic, D vendor_latin, E total_as_printed, F currency, G amount_iqd, H amount_usd_cents, I confidence, J notes.

    GOOGLE SHEETS (installs nothing): File > Import > Upload > select receipts-batch-01.csv. Set 'Import location' to 'Create new spreadsheet', 'Separator type' to 'Comma', and leave 'Convert text to numbers, dates and formulas' set to YES. Yes really, leave it on. The # in column E already stops that column being converted, and turning conversion off would make columns G and H text, which breaks step 20.

    LIBREOFFICE CALC: File > Open, choose the file, and the Text Import dialog appears. Set 'Character set' to 'Unicode (UTF-8)'. Under Separator Options tick 'Separated by' and tick only 'Comma'. Set 'String delimiter' to the double-quote character. LEAVE 'Format quoted field as text' UNTICKED. This recipe quotes every field, so ticking it would turn your amounts into text and step 20 would return 0. Leave all columns on 'Standard'.

    MICROSOFT EXCEL (Windows): do NOT double-click the .csv. Excel will open it in the Windows codepage and the Arabic becomes question marks. Instead open Excel first, then Data > From Text/CSV, choose the file, set 'File Origin' to '65001: Unicode (UTF-8)', set 'Delimiter' to 'Comma', and click Load.

    One cosmetic thing you can ignore: column B may be displayed in your local date format instead of as it was written. The underlying date is the same.

  16. Step 16 / 25All platforms

    Delete this batch from AI Studio now that the file is safely on your own computer.

    Check it worked

    Reload aistudio.google.com and look at the list of saved prompts or history in the left-hand panel. The batch you just did must not be there. Open the panel and read through it, if you have used AI Studio before, there may be older prompts sitting there that you have forgotten about; deal with those too.

    Note

    AI Studio has a save-and-share mechanism, Google's own quickstart describes being able to 'save your prompt to work on later and share with others' (read from https://ai.google.dev/gemini-api/docs/ai-studio-quickstart in this session), so assume that anything you did is still sitting in that account until you remove it. That same page documents nothing about retention or deletion of saved prompts, so do not assume anything happens on its own. On the shared office account a five-person NGO typically uses, every colleague with the password can open it and read your receipts. On a borrowed or confiscated laptop with a live session, so can whoever is holding it. Delete it.

    BE CLEAR ABOUT WHAT DELETING DOES AND DOES NOT DO. It closes the local and shared-account exposure, which is real and worth closing. It does NOT undo the free-tier exposure: Google's terms state no retention period for Unpaid Services data and say nothing about recalling content already used for product improvement or already read by a human reviewer. I checked. Treat that part as permanent. You accepted it in step 10.

  17. Step 17 / 25All platforms

    Repeat steps 11 through 16 for the rest of envelope A, ten receipts at a time, saving each batch as its own file: receipts-batch-02.csv, receipts-batch-03.csv, and so on.

    Copy this exactly

    receipts-batch-02.csv

    Check it worked

    Every photo in the folder now appears in the file column of exactly one batch spreadsheet. Tick the photos off against the batch files. A photo that is in no batch is a receipt that has disappeared from your accounts.

    Note

    Keep the batches as separate files until they have all passed steps 18 to 21. It is much easier to throw away and redo one bad batch of ten than to find the bad rows inside one file of eighty. Each finished, verified batch is a complete unit of work, if you have twenty minutes this week and not four hours, do one batch and stop. That also means a free-tier quota error costs you at most the batch you were in the middle of.

    Your last batch of the month will almost certainly be shorter than ten. That is fine, but remember two things: trim the numbered filename list in step 12 to the real number, and change the 11 in the step 18 formulas to match.

  18. Step 18 / 25All platforms

    CHECK 1, the count block. In each batch spreadsheet, click cell L2 and type these six formulas down column L, one per row. They tell you in one glance whether anything was silently dropped.

    Copy this exactly

    =COUNTA(A2:A11)
    =COUNTIF(F2:F11,"IQD")
    =COUNT(G2:G11)
    =COUNTIF(F2:F11,"USD")
    =COUNT(H2:H11)
    =COUNTIF(F2:F11,"UNKNOWN")

    Check it worked

    Four rules, all of which must hold before you go on. (1) L2 must equal the number of photos in this batch, ten, or fewer for your last batch. (2) L3 must equal L4. (3) L5 must equal L6. (4) L7 must be 0. If all four hold, nothing has been dropped and every amount is a real number the spreadsheet can add. If any fails, see the note.

    Note

    WHAT EACH LINE MEANS. L2 counts the rows that actually arrived. L3 counts how many receipts the model said were priced in dinars; L4 counts how many dinar amounts the spreadsheet was able to read as NUMBERS. L5 and L6 do the same for dollars. L7 counts receipts whose currency the model could not determine.

    IF L2 IS LESS THAN THE NUMBER OF PHOTOS: a receipt vanished between the upload and the file. Go back to step 13 for that batch. Do not carry on, no amount of checking the other rows will reveal a row that is not there.

    IF L3 IS BIGGER THAN L4 (or L5 bigger than L6): some amount cells are not numbers. This is the single most dangerous state in the whole recipe, because SUM silently skips them and the total in step 20 will simply be too small with no warning of any kind. There are three usual causes: the model wrote UNREADABLE or left a cell empty because it could not read a digit (correct behaviour, go to the paper and type the number in yourself); the amount came in with a stray separator or space (delete the separator so only digits remain); or the whole column imported as text (look at the alignment, text hugs the left edge, numbers hug the right, and redo the import following step 15).

    IF L7 IS NOT 0: one or more receipts have no currency. Find them by looking down column F for UNKNOWN, take those receipts out of envelope A, read the currency off the paper, and fill in column F and the correct amount column by hand.

    IF A FORMULA SHOWS AN ERROR instead of a number: some language settings use a semicolon instead of a comma inside formulas. Retype it as =COUNTIF(F2:F11;"IQD") and so on.

    IF THIS BATCH HAS FEWER THAN TEN RECEIPTS: change every 11 in the formulas to 1 plus the number of receipts in this batch. Seven receipts means A2:A8, F2:F8, G2:G8, H2:H8.

  19. Step 19 / 25All platforms

    CHECK 2, the digit check. Read across each row comparing column E (total_as_printed) against column G or H, using this conversion table. You are checking the model's own arithmetic against its own transcription, without going back to the paper.

    Copy this exactly

    ٠=0  ١=1  ٢=2  ٣=3  ٤=4  ٥=5  ٦=6  ٧=7  ٨=8  ٩=9
    ۰=0  ۱=1  ۲=2  ۳=3  ۴=4  ۵=5  ۶=6  ۷=7  ۸=8  ۹=9

    Check it worked

    For every dinar row, the digits in column E (ignoring the leading # and any separator) must be the same digits, in the same order, as column G. For every dollar row, the digits in column E must match column H with the decimal point removed, $25.00 in column E is 2500 in column H, so four digits either way. Count the digits in each pair before you read them. If the counts differ, stop and look at the paper.

    Note

    Print this table and tape it above the desk. The top row is the ARABIC-INDIC block (Unicode U+0660 to U+0669) and the bottom row is the EXTENDED ARABIC-INDIC block (U+06F0 to U+06F9); both are in the Unicode Character Database and Iraqi thermal printers emit both. The four traps, in order of how much money they cost: (a) ٥ is FIVE but it is drawn as a circle and looks exactly like a Western 0, check every zero-looking character; (b) ٠ is ZERO but it is drawn as a small dot, which at thermal-print resolution is nearly identical to the Arabic decimal separator ٫. This is how a total gains or loses a factor of a thousand; (c) the two rows of the table above are DIFFERENT Unicode blocks, so ٤٥٦ and ۴۵۶ are the same numbers in different shapes and models confuse them; (d) ٦ resembles a Western 7 and ٧ resembles a Western V.

    FOR SORANI RECEIPTS this check is compulsory, not optional, and so is checking the vendor name character by character. There is no published accuracy evidence for Kurdish Sorani on any model in this recipe, the one number that circulates, Surya's 93.9% for 'ku', comes from a table with no script column, so it does not say whether it tested Sorani in Arabic script or Kurmanji in Latin script, and it is not evidence for your receipts. Erbil receipts that print the total twice, in Kurdish and in Arabic or English, are a gift: the second printing is a free check.

    DOLLAR ROWS HAVE THEIR OWN TRAP: the model must have moved the decimal point, not deleted it. $25.00 becomes 2500, but $25 also becomes 2500 and $2,500 becomes 250000. Read the printed form in column E and satisfy yourself the cents are where they should be.

  20. Step 20 / 25All platforms

    CHECK 3, reconcile against your own hand, one currency at a time. This is the step that separates a spreadsheet you can put in a donor report from a machine that invents your accounts.

    Copy this exactly

    =SUM(G2:G11)
    =SUM(H2:H11)/100

    Check it worked

    Both numbers must match your calculator EXACTLY, digit for digit, not approximately, not to the nearest thousand. The dinar sum must equal your dinar calculator total. The dollar figure must equal your dollar calculator total, in dollars and cents. If both match, this batch is trustworthy and you have earned the right to move on.

    Note

    DO IT IN THIS ORDER, and do the paper first. (1) Take this batch's receipts out of envelope A. (2) Split them into a dinar pile and a dollar pile. That is why you tallied currencies in step 2. (3) Add the dinar pile on a calculator with your own fingers and write the answer on a sticky note. (4) Add the dollar pile the same way and write that on the sticky note too. (5) ONLY NOW go to the spreadsheet, click cell L9, and type the two formulas above, one per row. L9 gives you the dinar total; L10 gives you the dollar total in dollars and cents.

    WHY THE CURRENCIES ARE SEPARATE: adding a $500 hotel to a 3,000 IQD taxi produces a number that is not money. If you had one total column, this check could never pass, even when every single transcription was perfect, and a reader who shrugged and moved on would be shipping a report they had been told was verified.

    IF THE TWO DO NOT MATCH, the AI is wrong and your arithmetic is right. Read the difference, because it names the fault: a difference that is an exact multiple of 900 or 9000 is one digit misread; a difference of roughly a thousandfold on one row is the separator trap from rule 7 of the prompt; a difference of roughly a hundredfold on a dollar row is a misplaced decimal in the cents; a difference equal to one whole receipt is a duplicated or dropped row. Check each receipt in the batch against the paper until you find it.

    IF THE SUM COMES OUT AS 0 OR OBVIOUSLY TOO SMALL: go back to CHECK 1. Either the column is text (look at the alignment) or some cells are empty. SUM ignores both without saying anything, and that silence is the worst failure mode in this whole recipe.

    Adjust the column letters and the row range if your batch is short or your columns landed differently, and remember that some language settings need semicolons instead of commas inside formulas.

  21. Step 21 / 25All platforms

    CHECK 4, sort each currency and look at the ends, then open every LOW and MEDIUM row.

    Check it worked

    You have personally looked at the paper for: the three largest and three smallest dinar amounts, the three largest and three smallest dollar amounts, and every row whose confidence column says LOW or MEDIUM. Each one either matches the paper or has been corrected by hand.

    Note

    HOW TO SORT WITHOUT SCRAMBLING THE ROWS: select ALL your data including the header row, then Data > Sort range (Sheets) / Data > Sort (Calc and Excel), tick 'Data has header row', and sort by amount_iqd, largest first. Never sort a single column on its own. It detaches the amounts from their receipts.

    Sort by amount_iqd first and look at the top three and bottom three. Then sort by amount_usd_cents and do the same. Sorting the two currencies separately is the whole point: in a single mixed column a $500 hotel sorts below a 3,000 IQD taxi and the outlier check tells you the opposite of the truth.

    Misread digits almost never produce a plausible number; they produce an absurd one. A 250,000 IQD taxi and a 3 IQD generator repair both jump out of a sorted column in one second.

    Then filter or sort column I and open every row marked LOW or MEDIUM against the paper. That is what you made the model produce that column for. When you are done, sort back by date. Before the file goes to a donor, delete columns I and J (confidence and notes), but keep an unedited copy with them intact for your own audit trail.

  22. Step 22 / 25All platforms

    Make one combined sheet from the verified batches, then open envelope B and type those receipts into it by hand. Do not photograph them and do not upload them.

    Check it worked

    The combined sheet's row count equals the number of receipts in envelope A plus the number in envelope B. Run the CHECK 1 count block again on the combined sheet, widening the ranges to cover every row (for example A2:A200), and confirm the four rules still hold.

    Note

    Create a new spreadsheet called all-receipts-[month], paste in the header row once, then paste the verified data rows from each batch file underneath. Only combine batches that have passed steps 18 to 21. That is the whole reason they were separate files.

    Then type envelope B in at the bottom. For a small organisation this is usually a couple of dozen receipts a month and takes well under half an hour. That half hour is the entire price of not putting a map of your staff's movements onto someone else's servers, and it is the best value in this recipe. Fill the columns exactly as the model would have: put the printed total with a leading # in column E, the currency in F, the whole dinars in G or the whole cents in H, HIGH in column I, and 'typed by hand' in column J so a future colleague knows why these rows look different.

    Envelope B goes back to wherever your organisation keeps sensitive paper. Not on the desk.

  23. Step 23 / 25All platforms

    Decide where this file lives and what happens when you send it, before you send it. A .csv cannot carry a password. This is where readers used to hit a wall, so read the note before you try.

    Check it worked

    You can answer three questions out loud: where the file is stored, whether it is protected by a password or encryption, and who outside your organisation will now hold a copy. If any answer is 'I don't know', it is not finished. And the specific test for the password: close the protected file and open it again. It must ask you for the password. If it opens straight into the data, it is not protected.

    Note

    The assembled file is more sensitive than the shoebox was. The shoebox was a heap of paper nobody could search; this is a sorted, dated, searchable list of where your organisation spent money, with vendor names and dates, and it fits in an email attachment.

    (1) A .CSV CANNOT HOLD A PASSWORD. The format has no encryption of any kind. In Excel, 'Encrypt with Password' is unavailable while a .csv is open; in LibreOffice Calc, the 'Save with password' tick box is greyed out for the CSV file type. So keep the .csv as the plain working file and save a PROTECTED COPY in a format that can actually hold a password: LIBREOFFICE CALC: File > Save As, set 'File type' to 'ODF Spreadsheet (.ods)', tick 'Save with password', click Save, and set the password when prompted. EXCEL: File > Save As, set the type to 'Excel Workbook (.xlsx)', save it, then File > Info > Protect Workbook > Encrypt with Password. IF THE DONOR INSISTS ON A .CSV: put the .csv inside an encrypted archive instead of pretending the .csv is protected. On Windows with 7-Zip: right-click the file > 7-Zip > Add to archive, set 'Archive format' to 7z, type a password, and tick 'Encrypt file names'. On macOS or Linux the equivalent is any archiver that offers AES encryption. Then delete the unprotected .csv from the Downloads folder rather than leaving it beside the protected one. A password is only as good as how you share it, so send it by a different channel from the file, if the file goes by email, the password goes by phone or Signal, never in the same message.

    (2) Do not keep it in the same cloud folder as the receipt photos. Two copies of the same exposure in one place is one search away from being one exposure.

    (3) Delete the receipt photos from the working folder once the spreadsheet is verified and backed up, or move them to the same protected place.

    AND BE HONEST ABOUT THE DONOR. Emailing this file to a donor is a third-party disclosure of your vendors, your dates and, by inference, your locations, to an organisation in another jurisdiction with its own retention policy and its own auditors. That is usually a perfectly reasonable thing to do. It is what the grant agreement asks for, but it is a disclosure, and it deserves the same one-sentence decision as the upload in step 10, not an unthinking Send.

  24. Step 24 / 25All platforms

    Write four lines in your organisation's files recording what you just did, and keep them with the spreadsheet.

    Copy this exactly

    Receipts for [month]: photographed and transcribed using Google AI Studio ([the model name you actually picked], free tier) on [date] by [name], signed in on the Google account [account], which is held by [person].
    Sending organisational financial records to the unpaid tier was approved by [name] on [date], in the knowledge that Google's terms say "Do not submit sensitive, confidential, or personal information to the Unpaid Services".
    [N] receipts judged sensitive were excluded from the upload and typed by hand.
    All totals reconciled against a hand-added calculator total, per currency, on [date]; discrepancies found: [none / list].

    Check it worked

    Read the four lines back. Every square bracket has been replaced with a real name, a real date or a real number. A line still containing brackets is a line that will mean nothing to the auditor, the donor or the colleague who inherits this next year.

    Note

    Most of the organisations this recipe was written for have no written AI policy at all. Four lines a month is not a policy, but it is the record that lets an auditor, a donor or your own successor understand how the numbers were produced and where to look if one is wrong.

    Write in the model name you actually selected in step 9, not the one printed in this recipe, model names turn over every few months and a log that names the wrong one is worse than a log that names none.

    The second line matters more than it looks. It names the person who accepted the risk, and it states the risk accurately rather than pretending nobody noticed the vendor's own instruction. If someone later asks 'who decided it was acceptable to upload our accounts to Google', the answer should be a name and a date, not a shrug.

    The Google account line matters because the account holder is the identified party in Google's records, and on a shared office account that is often not the person who did the work.

    Writing these lines also forces you to notice, month after month, whether you are actually doing the verification in steps 18 to 21 or have quietly stopped.

  25. Step 25 / 25All platforms

    OPTIONAL OFFLINE LANE, only if you decided in step 10 that even ordinary receipts cannot leave the building. Read the warning in the note BEFORE you spend an hour on this, because for Arabic totals the honest answer is usually 'type them by hand instead'.

    Copy this exactly

    https://ollama.com/download

    Check it worked

    After the model has downloaded, turn your Wi-Fi OFF completely, drag a receipt photo into the chat and ask it something. If it still answers, it is genuinely running on your machine and nothing is leaving. Then read its output against the paper: if the total it gives you is wrong, that is the expected result for Arabic, not a setup mistake.

    Note

    WINDOWS AND macOS: download the Ollama desktop app from the link, open it, and in the model box type qwen3-vl:4b. Then drag a receipt photo into the chat window and paste the same prompt from step 12 (drop the F3 code-block rule; a small model will ignore it). No terminal is needed.

    LINUX: there is no desktop app, Ollama's own Linux download page offers only a shell install. Open a terminal and run: curl -fsSL https://ollama.com/install.sh | sh then: ollama run qwen3-vl:4b and type your prompt with the image path inside it, for example: Read this receipt: ./IMG_2041.jpg

    SMALLER AND FASTER ALTERNATIVES, with the download sizes shown on ollama.com when I checked (verify them on the page before you start a download on a metered connection): qwen3-vl:2b at 1.9 GB for an older laptop, qwen3-vl:4b at 3.3 GB, and glm-ocr, a dedicated 0.9B-parameter OCR model at 2.2 GB for the default tag or 1.6 GB for glm-ocr:q8_0. glm-ocr's own documented syntax is: ollama run glm-ocr Text Recognition: ./image.png

    THE WARNING. On KITAB-Bench, the standing Arabic OCR benchmark, models of this family scored a Character Error Rate of 1.20 (Qwen2.5-VL-7B) to 1.48 (Qwen2-VL-7B). A CER above 1.0 means the output is worse than useless. Qwen3-VL and glm-ocr are newer than that benchmark and nobody has published Arabic numbers for them, so they might be better. That is genuinely unknown, not a reassurance. Expect it to be slow on a laptop CPU: minutes per image, not seconds. And expect to check every number by hand.

    USE THIS LANE FOR: Latin-script receipts with Western digits; building a private searchable index of your own archive; work where a wrong number is embarrassing rather than disqualifying. DO NOT USE IT FOR: Arabic or Kurdish totals going into a donor report. For those, the genuinely local option is a human typing the number. That is step 22, and for a couple of dozen receipts it takes well under half an hour and is correct every time.

How to know the whole thing worked

There are four checks and they run in this order: the count block (step 18), the digit check (step 19), the hand reconciliation (step 20) and the sort-the-ends check (step 21). Do not drop any of them when you are busy. They are not a quality polish on top of the output. They are the part that turns the output into something you can put your name to.

THE ONE THAT MATTERS MOST is step 20, and you must do it in the right order. Take one batch's receipts out of the envelope. Split them into a dinar pile and a dollar pile. Add each pile on a phone calculator with your own fingers and write both answers on a sticky note. ONLY THEN open the spreadsheet, type =SUM(G2:G11) for dinars and =SUM(H2:H11)/100 for dollars, and compare. The two pairs of numbers must match exactly, digit for digit, not approximately, not to the nearest thousand. Reconciling each currency separately is not fussiness: in Erbil and Baghdad a normal month contains both, and a single mixed total can never match a calculator, even when every transcription is perfect.

If they match, the tool worked on those receipts and you have earned the right to trust that batch. If they do not match, the AI is wrong and your arithmetic is right; find the row that differs by checking each receipt against the paper. This is the answer to the fear that the machine invents things: it does, sometimes, and this is how you catch it in about two minutes.

THE ONE PEOPLE SKIP AND SHOULD NOT is step 18, because it catches the failures that make step 20 lie to you. If a receipt vanished between the upload and the file, or an amount cell came in as text instead of a number, or the model left an amount blank because it could not read a digit, then SUM silently skips it and your total is quietly too small with nothing on screen to warn you. The count block catches all three: the number of rows must equal the number of photos, the number of receipts marked IQD must equal the number of dinar amounts the spreadsheet can actually add, the same for USD, and no receipt may be left with an unknown currency. Four comparisons, six formulas, thirty seconds.

A GOOD OUTPUT LOOKS LIKE THIS. Column E shows something like #٢٥٬٠٠٠, the printed total, left-aligned, with its original Arabic digits and its original separator, preserved exactly. Column F says IQD. Column G says 25000, right-aligned against the edge of the cell, no dot and no comma anywhere. Column H is empty on that row. Column I says HIGH and column J says OK. A dollar row is the mirror image: column E reads #$25.00, F says USD, G is empty, H says 2500. If column G or H is left-aligned, or shows 25.000, or shows 25, something has gone wrong and step 20 will not save you, fix the import or the row first.

A FAST SECOND CHECK for every batch: sort by amount_iqd and look at the largest and smallest three, then sort by amount_usd_cents and do the same. A misread Arabic digit almost never produces a plausible expense. It produces a 250,000 IQD taxi or a 3 IQD generator repair, and those are visible from across the room.

AND ONE CHECK AT THE VERY END, in step 23: close the protected copy of the finished file and open it again. If it does not ask for a password, it is not protected, and if you saved it as a .csv, it cannot be, because the format has no encryption.

What goes wrong, and what to do about it

  • THE SUM RETURNS ZERO AND YOU CANNOT TELL WHY. If the amount columns are imported as text, every SUM in step 20 returns 0 and the reconciliation fails on every batch, even when the transcription is perfect. A reader who cannot tell a formatting artefact from a real error will either give up on the check or, worse, decide the check is unreliable and stop doing it. FIX: this is why step 15 tells you NOT to force any column to Text and specifically to leave LibreOffice's 'Format quoted field as text' unticked, and why the # marker in prompt rule 5 protects column E instead. Diagnose it by alignment: numbers hug the right edge of the cell, text hugs the left. The count block in step 18 catches it too, the IQD count will exceed the number of dinar amounts the spreadsheet can add.
  • A DOLLAR RECEIPT IS MULTIPLIED OR DIVIDED BY 100. In Erbil and Baghdad, hotels, generators, rent, many services and most NGO procurement are priced in USD. A rule written only for dinars ('whole number, no separator, fils are not used') turns $25.00 into 2500. FIX: prompt rules 6, 7 and 8 scope the whole-dinar convention to IQD only, give USD its own explicit convention in whole cents, and force the model to read the currency off the paper rather than infer it. The digit check in step 19 then catches a misplaced decimal because column E still shows the printed form.
  • MIXED CURRENCIES MAKE THE RECONCILIATION UNPASSABLE. Adding a $500 hotel to a 3,000 IQD taxi produces a number that is not money, so the check can never match the calculator, and sorting a mixed column puts the hotel below the taxi so the outlier check inverts. FIX: two separate amount columns, a currency tally on paper in step 2, per-currency reconciliation in step 20 and per-currency sorting in step 21.
  • THE MODEL PADS A SHORT FINAL BATCH WITH INVENTED ROWS. Almost no month divides into tens. If the prompt hardcodes 'output exactly 10 rows' and you upload seven, a model asked for ten will often produce ten, three of them fabricated, and fabricated rows look exactly like real ones. FIX: the step 12 prompt takes its row count from the numbered filename list rather than from a fixed number, and tells the model to stop and say so if the image count and the filename count disagree. Step 13 checks the row count against the thumbnails in both directions, too few AND too many, and step 18's L2 line catches it a third time.
  • THE TOTAL IS OUT BY A FACTOR OF 1000 AND NOBODY NOTICES. ISO 4217 formally gives the Iraqi dinar three decimal places (IQD, CcyNbr 368, CcyMnrUnts 3) even though fils are not used in practice, so a model that 'knows' about IQD may read a printed ٢٥٬٠٠٠ as twenty-five dinars instead of twenty-five thousand. FIX: rule 7 of the prompt forbids any separator in amount_iqd, states explicitly that fils are not used, and gives the worked example using the ARABIC THOUSANDS SEPARATOR (U+066C, ٬) rather than the decimal one. If a receipt genuinely prints the ARABIC DECIMAL SEPARATOR (U+066B, ٫) as a thousands mark, rule 7 makes the model flag it in notes and drop to MEDIUM confidence. If it still slips through, step 20 shows a thousandfold discrepancy on a single row.
  • ARABIC-INDIC FIVE (٥) IS READ AS ZERO. ٥ is drawn as a circle and is visually identical to a Western 0 at thermal-print resolution, so ٥٠٠ can become 000 or 500 depending on the model's mood. FIX: the conversion table in step 19, and counting digits, column E and the amount column must contain the same number of digits.
  • ARABIC-INDIC ZERO (٠) IS A DOT, and the Arabic decimal separator (٫, U+066B) is also a small mark, so on a faded thermal receipt they are nearly indistinguishable. A lost zero or an invented separator is a ten-fold or thousand-fold error. FIX: check any total whose digit count changed between column E and the amount column, and go back to the paper.
  • TWO DIFFERENT ARABIC DIGIT SYSTEMS APPEAR ON THE SAME PILE OF RECEIPTS. Unicode has ARABIC-INDIC digits at U+0660-U+0669 (٠١٢٣٤٥٦٧٨٩) and EXTENDED ARABIC-INDIC digits at U+06F0-U+06F9 (۰۱۲۳۴۵۶۷۸۹), whose four, five and six are drawn differently (٤٥٦ vs ۴۵۶). Iraqi thermal printers configured for Persian or Urdu emit the second set. Tesseract issue #1193, open since October 2017 and last updated in December 2025, is still collecting reports of exactly this mixture coming out garbled. FIX: the conversion table in step 19 covers both rows. Do not assume every receipt in the pile uses the same set.
  • THE DIGITS COME OUT IN THE WRONG ORDER. Arabic script runs right to left but numbers inside it run left to right, and OCR tools mishandle the boundary. EasyOCR issue #1059, open since June 2023, shows a ground-truth ۱٤٤۲٦۷ coming back as ٤٢٦٧ ١٤, every digit recognised, the order destroyed. Tesseract issue #2263 documented the same thing and is now closed, but #1193 is still open and still collecting reports, so do not assume the Arabic language data has caught up. FIX: this is a reason not to use Tesseract or EasyOCR on Arabic receipts at all. On the cloud models, the digit check in step 19 catches it, because a reordered total will not match the printed form in column E.
  • A RECEIPT SILENTLY DISAPPEARS FROM THE BATCH. You upload ten, the model returns nine, and the missing expense is simply absent from your report, no error message, nothing red. FIX: the row-count line of the count block in step 18, run on every batch, every time, plus the tick-off against the photo folder in step 17. This is the most common failure and the easiest to miss.
  • THE FILE COLUMN COMES BACK AS 'image 1' TO 'image 10' AND YOUR AUDIT TRAIL IS GONE. AI Studio passes images to the model as image data, not as your phone's filenames, so a prompt that simply asks for 'the filename' gets a placeholder. Three weeks later, when a donor queries row 34, you have no way to find the paper. FIX: step 12 pastes the filenames as a numbered list in upload order and rule 1 maps image N to filename N; step 13 checks the column before you copy anything.
  • THE ROW SHIFTS SIDEWAYS BECAUSE A NOTE OR A VENDOR NAME CONTAINS A COMMA. In CSV a bare comma ends the field, so a note like 'two totals printed, took the lower one' turns one row into ten fields plus an extra, and every column after it moves one place left. Amounts land in the confidence column and nothing looks obviously broken. FIX: format rule F1 of the prompt requires every field, including the header and including empty fields, to be wrapped in double quotes; step 13 checks that before you paste.
  • THE COPY FROM THE SCREEN MERGES OR REWRAPS LINES. AI Studio renders the reply as formatted text; selecting it with the mouse can join rows together, which produces exactly the vanishing-receipt failure the count block is there to catch. FIX: format rule F3 asks for a single fenced code block, which gives you a one-click copy button and the exact characters; delete the three backticks when you paste into the text editor.
  • THE MODEL INVENTS A VENDOR NAME. Faced with a smudged Iraqi, Kurdish or Turkmen business name it does not recognise, a language model will produce a plausible one rather than admit defeat. FIX: rule 3 of the prompt forbids substituting a business it thinks the name resembles and requires UNKNOWN when guessing. Spot-check vendor names against the paper for any row where confidence is not HIGH, and for Sorani receipts, check every one.
  • THE SUBTOTAL IS CAPTURED INSTEAD OF THE GRAND TOTAL. Many receipts print a subtotal, a tax or service line, and then the real total; some print the total twice. FIX: rule 11 of the prompt makes the model flag 'two totals printed; took the lower one' in the notes column. Read the notes column in step 21.
  • FLASH GLARE WIPES OUT THE TOTAL. Thermal paper is glossy and a phone flash burns a white band across it, usually across the bottom where the total sits. FIX: turn the flash off, use side daylight, and check three photos at full zoom before you leave the desk in step 3, if you cannot read it, no model will.
  • THE RECEIPT HAS FADED TO NOTHING. Thermal print fades with heat and months; a receipt left in a car in an Iraqi summer can be blank by September. FIX: photograph receipts the week you receive them. For an already-faded one, tilt it under a light until the printing catches the sheen. If it is truly gone, no tool recovers it, record it as a manual entry with a note.
  • YOU HIT THE FREE-TIER QUOTA HALFWAY THROUGH AND LOSE THE BATCH. Google no longer publishes a free-tier daily limit in its documentation. Its rate-limits page tells you to view your active rate limits in AI Studio instead, so you cannot plan around a number. FIX: work in batches of ten, save each batch's CSV and complete its checks before starting the next, and if you get a quota error, stop for the day and resume from that batch. Everything already saved is already good.
  • THE CSV OPENS AS ROWS OF QUESTION MARKS OR MOJIBAKE. The file was saved or imported without UTF-8, on Windows, most often because the .csv was opened by double-clicking it into Excel. FIX: re-save as UTF-8 (step 14) and re-import choosing UTF-8, using Data > From Text/CSV in Excel rather than double-clicking (step 15). Nothing is lost; you redo two steps.
  • THE SPREADSHEET REFORMATS YOUR EVIDENCE. Excel and Calc will happily turn a printed 25,000 into 25000 or 25.000 in the total_as_printed column, destroying the very comparison the digit check depends on. FIX: rule 5 of the prompt puts a # in front of that field, which makes every spreadsheet in every language setting treat it as text without you having to touch an import dialog.
  • YOU THINK YOU PASSWORD-PROTECTED THE FINISHED FILE, AND YOU DID NOT. A .csv has no encryption in the format at all: Excel's 'Encrypt with Password' is unavailable for it and LibreOffice's 'Save with password' tick box is greyed out. A reader who tries once, finds the option missing, and moves on ends up emailing the most searchable document their organisation owns in the clear. FIX: step 23 saves a protected copy as .ods or .xlsx, or puts the .csv inside an encrypted archive, and the test is to close the file and reopen it, if it does not ask for a password, it is not protected.
  • THE WHOLE PILE IS ALREADY IN GOOGLE PHOTOS OR ICLOUD BEFORE YOU START. Default phone settings back up every photo within minutes, with GPS coordinates inside each file. All of the recipe's careful accounting of what leaves the device is beside the point if this has already happened. FIX: step 1, before any photograph is taken. It takes two minutes and it is the largest single leak in the whole workflow.
  • EXIF GPS TURNS THE MOVEMENT MAP FROM AN INFERENCE INTO A DATASET. Every phone photo carries precise coordinates and a capture time inside the file, and those bytes travel with the upload. FIX: turn location off in the camera (step 1) and strip it from photos already taken (step 5, Windows / macOS / Linux routes given separately).
  • THE ENVELOPE MARKED 'SENSITIVE' DOES A SEARCHER'S WORK FOR THEM. Physically concentrating your most incriminating receipts in one clearly labelled place is the opposite of protective. FIX: step 2 labels the envelopes A and B, and envelope B is stored wherever the organisation already keeps sensitive paper, not on the desk.
  • THE PROMPT AND THE RECEIPT IMAGES SIT IN AI STUDIO FOR MONTHS. They stay attached to that Google account until someone removes them, which on the shared office account a small NGO typically uses means every colleague can read them, and on a borrowed or confiscated laptop means whoever holds it can. FIX: step 16 deletes each batch as soon as the CSV is safe. Be clear about what that does and does not fix: it closes the local and shared-account exposure, not the free-tier exposure, which you should treat as permanent.
  • THE FINISHED FILE IS TREATED AS ORDINARY. A sorted, dated, searchable list of your vendors and dates is more revealing than the shoebox ever was, and it fits in an email attachment. FIX: step 23 gives a concrete floor, a password-protected .ods or .xlsx copy or an encrypted archive, not in the same cloud folder as the photos, photos deleted once verified, and names the donor email as the third-party disclosure it is.
  • NOBODY DECIDED WHOSE GOOGLE ACCOUNT THIS IS. The account holder is personally the identified party in Google's records for every receipt uploaded, and a shared NGO account means shared visibility. FIX: decide before step 8 and record the account, the operator and the person who approved the upload in the log in step 24.
  • YOU REACH FOR TESSERACT, PADDLEOCR, SURYA OR EASYOCR because they are free and offline, and get numbers you cannot bank. On the KITAB-Bench Arabic benchmark their Character Error Rates were 0.54, 0.79, 4.95 and 0.58 respectively, against 0.13 for Gemini-2.0-Flash. FIX: do not use classical OCR engines on Arabic receipts. If you must stay offline, use the hand-typing route in step 22 for anything whose number matters.
  • YOU RUN A SMALL LOCAL VISION MODEL AND TRUST IT. Qwen2.5-VL-7B scored a Character Error Rate of 1.20 on Arabic in the same benchmark, above 1.0, meaning the output is worse than useless. Newer models like Qwen3-VL and glm-ocr may be better but no published Arabic receipt numbers exist for them. FIX: treat the offline lane in step 25 as unverified for Arabic and check every number by hand.
  • A COLLEAGUE ABROAD HOLDS THE PAID API KEY on your behalf, and now your financial records pass through their account, their billing history and their jurisdiction. FIX: if you go this route, decide it deliberately, write it into the log in step 24, and understand that the exposure moved rather than disappeared.
  • YOU BUDGET FROM A PRICE PRINTED IN A RECIPE. Vendor prices change, promotional rates expire, and a figure written for a September conference can be wrong by the time the grant is signed. FIX: this recipe deliberately carries no dollar figures at all. Open the vendor's own pricing page the week you need the number, and check whether the rate you are reading has an expiry date printed beside it.

How well it works in your language

Arabic (Modern Standard) · Iraqi Arabic · Kurdish (Sorani)

Arabic (Modern Standard)

Workable but not trustworthy without checking. Printed Modern Standard Arabic on a clean receipt is the best case, and the current frontier vision models are far better at it than any OCR engine. But 'best case' still means errors: on the KITAB-Bench Arabic OCR benchmark the strongest general model tested, Gemini-2.0-Flash, reached a Character Error Rate of 0.13, roughly one character in eight wrong, and the authors name 'numeral recognition errors' explicitly as one of the four standing limitations of current Arabic OCR, alongside complex fonts, word elongation and table structure detection. On the harder PDF-to-Markdown task the abstract says 'the best model Gemini-2.0-Flash achieves only 65% accuracy'. That benchmark tested an earlier generation, and Gemini-2.0-Flash has since been shut down; nobody has published equivalent numbers for the current Gemini, GPT or Claude models, so their Arabic receipt accuracy today is UNVERIFIED and may well be better. Assume it is not, and check. This sentence is repeated inside step 9 itself so that a reader who never reaches the bottom of this page still sees it at the moment they pick the model.

Iraqi Arabic

Iraqi dialect is almost irrelevant here and that is the point people get wrong. A receipt is not conversational text. It is a printed business name, a date, a list of items and a number. What actually breaks on Iraqi receipts is not dialect grammar, it is five specific things: thermal paper that has faded in a hot office or car; Iraqi and Kurdish and Turkmen vendor names that no model has a prior for and will 'correct' into something plausible; local abbreviations and trade names; the digits; and, in Erbil and Baghdad especially, the fact that the pile contains both dinar and dollar receipts, so 'the total' is not one kind of number. UNTESTED: I found no published benchmark on Iraqi thermal receipts specifically. Treat every vendor name the model produces as a guess and every total as unverified until you have checked it.

Kurdish (Sorani)

Weakest of the three, the least documented, and the place where you should trust this recipe least. Sorani is written in Arabic script with extra letters (ڕ ڵ ۆ ێ پ چ ژ گ) that most OCR training data underrepresents. Surya's own multilingual results file gives 'ku' a 93.9% score, which looks excellent, but the ISO code 'ku' is ambiguous between Kurmanji (Latin script) and Sorani (Arabic script), and that file's table has only three columns (Code, Language, Score) with no script or variant column at all, so that number should NOT be read as evidence for Sorani. I could not resolve the ambiguity from the project's documentation. Meanwhile Surya scored 4.95 CER on Arabic in KITAB-Bench, effectively a failure.

SAY THIS PART OUT LOUD: there is no published benchmark evidence, for any model in this recipe, on Kurdish Sorani receipts. When this recipe says 'for Sorani receipts use the cloud model', that is a judgement, not a measurement. It rests only on the general finding that vision-language models beat OCR engines on Arabic script, and Sorani was not what was tested. Erbil receipts are frequently bilingual Kurdish/Arabic or Kurdish/English, which genuinely helps, because a second rendering of the same total gives you something to check against. Practical advice: for Sorani receipts, treat the digit check in step 19 and the hand reconciliation in step 20 as compulsory rather than optional, and check every character of the vendor name against the paper rather than spot-checking.

What that rests on

KITAB-Bench: A Comprehensive Multi-Domain Benchmark for Arabic OCR and Document Understanding, arXiv:2502.14949, 8,809 samples across 9 major domains and 36 sub-domains. Table 6, CER/WER on Arabic, read from the paper's HTML in this session: Tesseract 0.54/0.84, EasyOCR 0.58/0.89, PaddleOCR 0.79/1.02, Surya 4.95/5.61, Qwen2-VL-7B 1.48/1.55, Qwen2.5-VL-7B 1.20/1.41, GPT-4o-mini 0.43/0.71, GPT-4o 0.31/0.55, Gemini-2.0-Flash 0.13/0.32, AIN-7B 0.20/0.28.

Tesseract's difficulty with Arabic numerals is not folklore, it is an open bug. Read from the GitHub API in this session: tesseract-ocr/tesseract issue #1193 'Arabic Numbers' was created 30 October 2017, is still OPEN, has 41 comments, and was last updated 7 December 2025. Issue #2047 'Arabic training data has room for improvement' was created 9 November 2018, is still OPEN, and has 21 comments. Issue #2263 'Numbers in Arabic script are getting reversed' was created 23 February 2019 and is now CLOSED, but #1193 is still collecting reports, so the recognition gap in the Arabic language data has not gone away. The same reversal problem is live in JaidedAI/EasyOCR issue #1059 'Problem in Extracting Arabic numerals from the OCR output', open since 21 June 2023, where the reporter's ground-truth ۱٤٤۲٦۷ came back as ٤٢٦٧ ١٤, the digits recognised, the order destroyed (issue body read in this session).

Digit-shape confusion is structural, not incidental. Read directly from the Unicode Character Database in this session: ARABIC-INDIC DIGIT ZERO at U+0660 through ARABIC-INDIC DIGIT NINE at U+0669 (٠١٢٣٤٥٦٧٨٩), and EXTENDED ARABIC-INDIC DIGIT ZERO at U+06F0 through EXTENDED ARABIC-INDIC DIGIT NINE at U+06F9 (۰۱۲۳۴۵۶۷۸۹), whose four, five and six are drawn differently (٤٥٦ vs ۴۵۶); Iraqi thermal printers emit both. Arabic script also has its own two separators, which are different characters with different meanings: U+066B is ARABIC DECIMAL SEPARATOR (٫) and U+066C is ARABIC THOUSANDS SEPARATOR (٬). Confusing the two is a thousand-fold error, so the worked example in the prompt uses U+066C (٢٥٬٠٠٠ = twenty-five thousand) and treats U+066B as a case the model must flag.

And ISO 4217 (SIX Group list-one.xml, read in this session) assigns IRAQ / Iraqi Dinar / IQD / CcyNbr 368 / CcyMnrUnts 3, three decimal places, even though fils are not used in practice, which is the mechanism behind the thousand-fold error described in the failure modes.

Software named in this recipe

  • Google AI Studio (aistudio.google.com), the main path
  • Gemini 3.7 Flash (gemini-3.7-flash), marked free of charge on the free tier when I checked Google's pricing page; re-check before you rely on it
  • Gemini 3.6 Flash (gemini-3.6-flash), also free-tier
  • Gemini 3.5 Flash (gemini-3.5-flash), also free-tier
  • Gemini 2.5 Flash (gemini-2.5-flash), also free-tier
  • Gemini 2.0 Flash (gemini-2.0-flash), NOW SHUT DOWN, listed under 'Previous models' on Google's docs; quoted in this recipe only as a benchmark datapoint, do not look for it in the model picker
  • Ollama desktop app (Windows and macOS; Linux is shell-install and terminal-only)
  • Qwen3-VL (qwen3-vl:2b, qwen3-vl:4b, qwen3-vl:8b), offline lane only
  • GLM-OCR (glm-ocr, 0.9B parameters), offline lane only
  • Tesseract, Surya OCR, PaddleOCR and EasyOCR, named only as the classical OCR engines this recipe tells you NOT to use on Arabic receipts
  • Google Sheets (the no-install spreadsheet)
  • LibreOffice Calc
  • Microsoft Excel
  • 7-Zip (Windows, for the encrypted archive in step 23)
  • exiftool (Linux only, for stripping GPS metadata)
  • Google Colab (the original module's delivery vehicle, removed in this rewrite)

Sources

  • Adapted from CDR workshop material, 'harcamalarinizi-dijitallestirin' (Digitise your receipts): https://github.com/cdrorgtr/cdr-ai/tree/main/harcamalarinizi-dijitallestirin, directory opened in this session; it contains README.md and main.ipynb and describes digitising receipts with OpenAI's GPT-4 Vision via a Google Colab notebook with Google Drive integration
  • KITAB-Bench: A Comprehensive Multi-Domain Benchmark for Arabic OCR and Document Understanding, arXiv:2502.14949, https://arxiv.org/abs/2502.14949 (abstract read in this session: 8,809 samples across 9 major domains and 36 sub-domains; the phrases 'by an average of 60% in Character Error Rate', 'the best model Gemini-2.0-Flash achieves only 65% accuracy', and the limitations list naming 'numeral recognition errors' all present)
  • KITAB-Bench Table 6, 'Performance comparison of models for OCR (image to text) tasks on our benchmark', https://arxiv.org/html/2502.14949v2 (CER/WER read in this session: Tesseract 0.54/0.84, EasyOCR 0.58/0.89, PaddleOCR 0.79/1.02, Surya 4.95/5.61, Qwen2-VL-7B 1.48/1.55, Qwen2.5-VL-7B 1.20/1.41, GPT-4o-mini 0.43/0.71, GPT-4o 0.31/0.55, Gemini-2.0-Flash 0.13/0.32, AIN-7B 0.20/0.28)
  • Google Gemini API Additional Terms of Service, https://ai.google.dev/gemini-api/terms (read in this session: the unpaid-tier sentences about Google using submitted content, about human reviewers reading, annotating and processing API input and output, and 'Do not submit sensitive, confidential, or personal information to the Unpaid Services'; the paid-tier sentence that Google 'doesn't use your prompts... or responses to improve our products'; and the absence of any stated retention period for Unpaid Services data)
  • Google Gemini API pricing, https://ai.google.dev/gemini-api/docs/pricing (read in this session ONLY to confirm which models are marked 'Free of charge' on the free tier: Gemini 3.7 Flash, 3.6 Flash, 3.5 Flash, 3.5 Flash-Lite, 3.1 Flash-Lite, 2.5 Pro and 2.5 Flash among others. This recipe quotes no prices from this page, open it yourself for the current rates)
  • Google Gemini API models list, https://ai.google.dev/gemini-api/docs/models (read in this session: Gemini 3.7 Flash listed as the latest Flash model with endpoint gemini-3.7-flash; Gemini 2.0 Flash listed under 'Previous models' as Shut down)
  • Gemini API and Google AI Studio available regions, https://ai.google.dev/gemini-api/docs/available-regions (opened in this session; Iraq is listed. No alphabetical run is quoted anywhere in this recipe on purpose, see whatIDeleted)
  • Google Gemini API rate limits, https://ai.google.dev/gemini-api/docs/rate-limits (read in this session: no free-tier requests-per-minute or requests-per-day figures are published; the page directs you to 'View your active rate limits in AI Studio')
  • Google AI Studio quickstart, https://ai.google.dev/gemini-api/docs/ai-studio-quickstart (read in this session: 'save your prompt to work on later and share with others'; the page documents nothing about retention or deletion of saved prompts)
  • Anthropic supported countries, https://www.anthropic.com/supported-countries (opened in this session; Iraq is listed under both the API and the Claude.ai sections)
  • OpenAI supported countries, https://developers.openai.com/api/docs/supported-countries (opened in this session; Iraq is listed)
  • Tesseract issue #1193 'Arabic Numbers', created 2017-10-30, state open, 41 comments, last updated 2025-12-07 (metadata read from the GitHub API in this session), https://github.com/tesseract-ocr/tesseract/issues/1193
  • Tesseract issue #2047 'Arabic training data has room for improvement', created 2018-11-09, state open, 21 comments (GitHub API, this session), https://github.com/tesseract-ocr/tesseract/issues/2047
  • Tesseract issue #2263 'Numbers in Arabic script are getting reversed', created 2019-02-23, state closed (GitHub API, this session), https://github.com/tesseract-ocr/tesseract/issues/2263
  • EasyOCR issue #1059 'Problem in Extracting Arabic numerals from the OCR output', created 2023-06-21, state open; the issue body read in this session gives the ground truth ۱٤٤۲٦۷ and the returned ٤٢٦٧ ١٤, https://github.com/JaidedAI/EasyOCR/issues/1059
  • Surya OCR full multilingual results, https://github.com/datalab-to/surya/blob/master/static/docs/multilingual.md (file read in this session: 'Overall pass rate: 87.2% across 91 languages (32,055 tests)'; ku Kurdish 93.9%; ar Arabic 72.7%; the table has three columns, Code, Language, Score, and no script or variant column, so 'ku' does not distinguish Sorani from Kurmanji)
  • Unicode Character Database, UnicodeData.txt, downloaded and read directly in this session, 0660 ARABIC-INDIC DIGIT ZERO, 0669 ARABIC-INDIC DIGIT NINE, 066B ARABIC DECIMAL SEPARATOR, 066C ARABIC THOUSANDS SEPARATOR, 06F0 EXTENDED ARABIC-INDIC DIGIT ZERO, 06F9 EXTENDED ARABIC-INDIC DIGIT NINE, https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt
  • ISO 4217 currency list (list-one.xml), downloaded and read directly in this session: CtryNm IRAQ / CcyNm Iraqi Dinar / Ccy IQD / CcyNbr 368 / CcyMnrUnts 3, https://www.six-group.com/dam/download/financial-information/data-center/iso-currrency/lists/list-one.xml
  • Ollama model library, qwen3-vl, https://ollama.com/library/qwen3-vl (read in this session: 2b 1.9 GB, 4b 3.3 GB, 8b 6.1 GB; run with ollama run qwen3-vl:4b)
  • Ollama model library, glm-ocr, https://ollama.com/library/glm-ocr (read in this session: 0.9B parameters, latest tag 2.2 GB, q8_0 tag 1.6 GB, documented syntax 'ollama run glm-ocr Text Recognition: ./image.png')
  • Ollama Linux download page, https://ollama.com/download/linux (read in this session: the install line is 'curl -fsSL https://ollama.com/install.sh | sh'; only a shell install is offered for Linux, no desktop package)
  • Debian package index, libimage-exiftool-perl, package name confirmed in this session via sources.debian.org, which returns it as an exact match, https://packages.debian.org/search?keywords=libimage-exiftool-perl

A CDR original, written for POINT Conference Iraq 7. Checked against vendor pages and package registries in August 2026; the sources are listed on this page.

What we could not verify

WHAT CHANGED SINCE THE 2024 ORIGINAL. The original told you to run a Colab notebook against GPT-4 Vision and get a tidy CSV. That framing is obsolete in two ways and wrong in a third. Obsolete: GPT-4 Vision is not a current product name, and the models that replaced it turn over every few months, which is why this rewrite names one current model at the point of use and tells you to check the vendor's own model list rather than trusting a name printed here. Obsolete: a Colab notebook plus a Google Drive folder of receipts is now both harder and more exposing than pasting ten photos into a browser tab, so this rewrite drops the notebook entirely, the Drive integration would have put the whole receipt archive in Google Drive, which is a bigger exposure, not a smaller one. Wrong: the original's promise of automatic, tidy, batch extraction is exactly the promise that produces bad accounting in Arabic, and no amount of model improvement has fixed it.

THIS VERSION CARRIES NO PRICES, ON PURPOSE. Earlier drafts of this recipe worked out a monthly cost for three vendors to two decimal places. Every one of those figures has been deleted. Some of them may well have been right, but a conference portal is read for a year, promotional rates expire, and a wrong number in a budget line is worse than a link. The cost section now points at the three vendors' own pricing pages and says the only thing about cost that is durably true: for a small NGO the monthly bill is not what stops you, the card is.

WHAT I VERIFIED IN THIS SESSION AND WHAT I DID NOT. Verified by opening the source: that Iraq is listed on Google's, Anthropic's and OpenAI's own country pages; that Gemini 3.7 Flash exists with that model ID and is marked free of charge on the free tier, along with the other Flash models named here; that Gemini 2.0 Flash is listed as shut down; that Google's unpaid tier trains on your data, permits human review, AND instructs you not to submit confidential information, while its paid tier does not train; that Google's terms state no retention period for unpaid-tier data; that the rate-limits page has stopped publishing free-tier numbers; that the AI Studio quickstart describes saving and sharing prompts. Verified from primary sources read directly: the Unicode code points for both Arabic digit blocks and both Arabic separators; that ISO 4217 assigns IQD CcyNbr 368 and CcyMnrUnts 3; the state, creation date and comment count of the three Tesseract issues and the EasyOCR issue, and the garbled Arabic string in the EasyOCR issue body; Surya's own multilingual scores and the shape of that table. Verified from the benchmark paper itself: the Table 6 CER and WER figures for all ten models and all three quoted abstract claims. Verified from the vendors' own pages: the Ollama model sizes and run syntax, and that Linux gets a shell install only. Verified from the Debian package index: the exiftool package name.

UNVERIFIED, AND YOU SHOULD TREAT THESE AS OPEN QUESTIONS. (1) No public benchmark measures the current frontier models on Arabic OCR. The best published Arabic number for any model is Gemini-2.0-Flash at CER 0.13, and that model has since been shut down. The current models are probably better; I cannot show you by how much. (2) Nobody has benchmarked anything on Iraqi thermal receipts specifically, which are a harder and dirtier case than the printed documents KITAB-Bench used. Every accuracy claim here is therefore an upper bound. (3) There is NO evidence, published anywhere, for any of these models on Kurdish Sorani. The recipe's advice to use the cloud model for Sorani receipts is a judgement extrapolated from Arabic-script results, not a measurement, and the steps say so at the point of use rather than only here. Surya's own table gives 'ku' 93.9% and Arabic 72.7%, which flatly contradicts its 4.95 CER in KITAB-Bench; the two are measuring different things, I could not reconcile them, and the table has no script column so 'ku' may be Kurmanji in Latin script. (4) Qwen3-VL and glm-ocr postdate the benchmark and their Arabic performance is unknown. (5) The exact Gemini free-tier daily request limit is no longer published, so the recipe cannot promise that a month of receipts finishes in one sitting, which is why the workflow makes every batch of ten a complete saved unit. (6) Whether an Iraqi-issued card will be accepted by any vendor's billing is not documented by any vendor; the widespread reports of declines are real but I could not verify them against a primary source. (7) Google's terms say nothing about whether content already used for product improvement or read by a human reviewer can be recalled. The recipe therefore treats free-tier submission as irreversible, which is the safe reading, not a documented one. (8) The time estimates in this recipe, an hour and a half for a first batch, half a day for a month, well under half an hour to hand-type envelope B, are my estimates, not measurements from watching anyone do it, and they are labelled as such where they appear.

WHAT THIS RECIPE HONESTLY DOES NOT DO. It does not make transcription trustworthy without a human. The verification in steps 18 to 21 is not an optional quality step you can drop when you are busy. It is the part that makes the output usable, and if you stop doing it you have built a machine that generates plausible wrong numbers for your donor. It does not give you free, private and accurate at the same time: free means Google reads your receipts and tells you in writing not to send them; private means either paying with a card you may not have, or accepting offline accuracy that does not work in Arabic. It does not solve the sensitive receipts; a human still types those, on purpose, and that is the correct answer rather than a consolation prize. It does not fit in two hours: budget an hour and a half for your first batch of ten and about half a day for a month, and take it one batch at a time. And it does not remove the underlying risk that a year of receipts, once assembled in one file, is a movement map of your organisation. That file is now more sensitive than the shoebox was, which is why step 23 exists.

All recipes