<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: FLOW by Vestelon</title>
    <description>The latest articles on DEV Community by FLOW by Vestelon (@vestelonflow).</description>
    <link>https://dev.to/vestelonflow</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3991476%2F2cf94fec-5193-48fa-af66-aa548db3698a.png</url>
      <title>DEV Community: FLOW by Vestelon</title>
      <link>https://dev.to/vestelonflow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vestelonflow"/>
    <language>en</language>
    <item>
      <title>The Freelancer Hidden Tax: Multi-Currency Income and Financial Blind Spots</title>
      <dc:creator>FLOW by Vestelon</dc:creator>
      <pubDate>Fri, 19 Jun 2026 09:01:15 +0000</pubDate>
      <link>https://dev.to/vestelonflow/the-freelancer-hidden-tax-multi-currency-income-and-financial-blind-spots-461a</link>
      <guid>https://dev.to/vestelonflow/the-freelancer-hidden-tax-multi-currency-income-and-financial-blind-spots-461a</guid>
      <description>&lt;h1&gt;
  
  
  The Freelancer Hidden Tax: Multi-Currency Income and Financial Blind Spots
&lt;/h1&gt;

&lt;p&gt;Remote work has created financial complexity most budgeting tools weren't designed for. If you earn USD while living in Europe, or GBP while based in Southeast Asia, you're dealing with structure that's genuinely hard to track.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; partly because of this problem. After processing thousands of multi-currency statements from international freelancers, here are the patterns that consistently appear.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Invisible Costs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Payment processor fees that don't look like fees&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PayPal, Wise, and Stripe all convert at rates slightly worse than mid-market. The difference doesn't appear as "fee" — it appears as a slightly lower deposit than expected. Over a year of regular payments, this is typically 1-3% of total income. It's invisible unless you compare each deposit amount to the invoice amount and the mid-market rate at the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Subscription creep in the work currency&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Freelancers maintain most software in USD: Figma, Notion, GitHub, AWS, Loom, Zoom. As the dollar strengthens against local currency, these subscriptions become proportionally more expensive — but the USD amount stays constant, so it doesn't feel like an increase. It only becomes visible when you calculate actual local-currency cost over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The invisible month&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Annual subscriptions, domain renewals, software licenses, and insurance premiums create months that look inexplicably expensive. Because these appear once a year, they're rarely budgeted. A 12-month statement view makes them immediately obvious.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Standard Apps Miss This
&lt;/h2&gt;

&lt;p&gt;Most budgeting apps work within one country via Open Banking. They can't see your Wise account AND your local bank simultaneously. They can't normalize across currencies to show real purchasing power trends.&lt;/p&gt;

&lt;p&gt;The PDF approach — download statements from each service, analyze together — sidesteps these limitations. Your Wise statement, local bank statement, and PayPal history become a single unified view.&lt;/p&gt;

&lt;p&gt;This is what &lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; does. Upload PDFs from all your financial accounts, get categorized spending across all of them with currency normalization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Fixes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Track FX rates on large invoices
   → Compare received rate vs. mid-market (xe.com)
   → Reveals which payment methods are actually expensive

2. Quarterly review (not monthly)
   → Annual charges only visible over longer windows

3. Download PDFs regularly
   → Most banks export 12 months at once
   → Don't wait until tax season
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;&lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; — PDF bank statement analyzer. First report free.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What payment processor gives you the most trouble for expense tracking? Genuinely curious what others have found.&lt;/p&gt;

</description>
      <category>freelance</category>
      <category>fintech</category>
      <category>remote</category>
      <category>career</category>
    </item>
    <item>
      <title>Why Bank Statement PDFs Are Still a Mess in 2026 (And What We Did About It)</title>
      <dc:creator>FLOW by Vestelon</dc:creator>
      <pubDate>Fri, 19 Jun 2026 08:56:39 +0000</pubDate>
      <link>https://dev.to/vestelonflow/why-bank-statement-pdfs-are-still-a-mess-in-2026-and-what-we-did-about-it-4n6j</link>
      <guid>https://dev.to/vestelonflow/why-bank-statement-pdfs-are-still-a-mess-in-2026-and-what-we-did-about-it-4n6j</guid>
      <description>&lt;h1&gt;
  
  
  Why Bank Statement PDFs Are Still a Mess in 2026 (And What We Did About It)
&lt;/h1&gt;

&lt;p&gt;Every developer who has tried to parse bank statement PDFs eventually reaches the same conclusion: there is no standard.&lt;/p&gt;

&lt;p&gt;I've been building &lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt;, a bank statement analyzer that supports 8 languages and 50+ bank formats. Here's what I wish someone had told me at the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  The PDF Standard Doesn't Help You
&lt;/h2&gt;

&lt;p&gt;PDF is a display format, not a data format. The specification defines how pixels render on screen, not how tables should be structured semantically.&lt;/p&gt;

&lt;p&gt;This means that what looks like a clean table in your PDF viewer might be stored internally as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Floating text boxes positioned to look like a table&lt;/li&gt;
&lt;li&gt;Actual table structures (rare, but exist)&lt;/li&gt;
&lt;li&gt;A scanned image with no extractable text at all&lt;/li&gt;
&lt;li&gt;A mix of all three across different pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same bank will often have 3-4 different PDF generations in circulation, because they've changed their banking software over the years. A customer downloading statements from 2019 and 2024 might get completely different file structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Seven Failure Modes
&lt;/h2&gt;

&lt;p&gt;After processing thousands of statements, these are the patterns that break naive extraction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Merged cells that span transaction rows&lt;/strong&gt;&lt;br&gt;
Some banks merge the date cell across multiple transactions on the same day. Your row parser gives you a date for the first transaction and nothing for the next 4.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Footer rows that look like transactions&lt;/strong&gt;&lt;br&gt;
"Balance carried forward: 4,521.00" parses exactly like a debit transaction unless you explicitly filter it out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Multi-page transactions&lt;/strong&gt;&lt;br&gt;
Long merchant descriptions sometimes wrap across page boundaries. The transaction starts on page 3 and the amount appears at the top of page 4.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Amount sign conventions&lt;/strong&gt;&lt;br&gt;
Some banks use positive/negative signs. Some use separate Debit/Credit columns. Some use red text for debits (invisible in text extraction). Some use parentheses for negative amounts. Some use D/C suffixes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Thousand separators&lt;/strong&gt;&lt;br&gt;
1,234.56 (US/UK), 1.234,56 (German), 1 234,56 (French), 1'234.56 (Swiss). All valid. All different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Date locale&lt;/strong&gt;&lt;br&gt;
"03/04/2024" means April 3rd or March 4th depending on the bank's country. You can't know without context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Currency symbols vs codes&lt;/strong&gt;&lt;br&gt;
€, EUR, Eur, eur, E — all appear in the wild for the same currency, sometimes in the same document.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Works: A Defensive Pipeline
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StatementParser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="c1"&gt;# 1. Try text extraction first
&lt;/span&gt;        &lt;span class="n"&gt;transactions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_try_text_extraction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_confidence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# 2. Fall back to OCR if text quality is low
&lt;/span&gt;            &lt;span class="n"&gt;transactions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_try_ocr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 3. Always validate output
&lt;/span&gt;        &lt;span class="n"&gt;transactions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_validate_and_clean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# 4. Flag low-confidence transactions rather than silently dropping
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_annotate_confidence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_confidence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
        &lt;span class="c1"&gt;# Check that amounts parse, dates are reasonable, no duplicates
&lt;/span&gt;        &lt;span class="n"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight: &lt;strong&gt;fail loudly, not silently&lt;/strong&gt;. A transaction that couldn't be parsed should be flagged, not dropped. Users need to know when their data is incomplete.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Maintenance Reality
&lt;/h2&gt;

&lt;p&gt;New bank formats appear constantly. A bank redesigns their statement template, and suddenly your parser that worked perfectly for 3 years breaks on their new PDFs.&lt;/p&gt;

&lt;p&gt;We run regression tests against a corpus of 500+ anonymized statement samples. Any code change that drops coverage on an existing bank format requires explicit sign-off before deployment.&lt;/p&gt;

&lt;p&gt;This is unglamorous work, but it's what separates a parser that works in demos from one that works in production.&lt;/p&gt;




&lt;p&gt;If you're building something that needs to parse financial PDFs, the open-source options (Camelot, Tabula, pdfplumber) are worth knowing — they're good starting points. The hard part is all the defensive logic around them.&lt;/p&gt;

&lt;p&gt;Questions welcome. This is one of those domains where every new edge case is genuinely interesting.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; — PDF bank statement analyzer, first report free.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>pdf</category>
      <category>fintech</category>
      <category>programming</category>
    </item>
    <item>
      <title>Parsing Arabic PDF Bank Statements: What I Learned Building a Multi-Language Analyzer</title>
      <dc:creator>FLOW by Vestelon</dc:creator>
      <pubDate>Fri, 19 Jun 2026 08:56:08 +0000</pubDate>
      <link>https://dev.to/vestelonflow/parsing-arabic-pdf-bank-statements-what-i-learned-building-a-multi-language-analyzer-1kg5</link>
      <guid>https://dev.to/vestelonflow/parsing-arabic-pdf-bank-statements-what-i-learned-building-a-multi-language-analyzer-1kg5</guid>
      <description>&lt;h1&gt;
  
  
  Parsing Arabic PDF Bank Statements: What I Learned Building a Multi-Language Analyzer
&lt;/h1&gt;

&lt;p&gt;When I started building &lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; — a bank statement PDF analyzer — I assumed Arabic would be one of the harder languages to support. I was right, but not for the reasons I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Right-to-Left Problem Isn't the Hard Part
&lt;/h2&gt;

&lt;p&gt;Most developers assume Arabic PDF parsing is hard because of right-to-left text direction. In practice, modern PDF libraries (pdfplumber, PyMuPDF) handle RTL text reasonably well. The text extraction itself usually works.&lt;/p&gt;

&lt;p&gt;The real challenge is &lt;strong&gt;positional logic&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Column Detection Breaks
&lt;/h2&gt;

&lt;p&gt;In a typical Western bank statement, you have columns roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Date | Description | Debit | Credit | Balance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The date is on the left, balance on the right. Column detection heuristics work because the layout matches left-to-right reading order.&lt;/p&gt;

&lt;p&gt;In an Arabic statement from ENBD or Mashreq, the layout is mirrored:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Balance | Credit | Debit | Description | Date
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try to apply the same column extraction logic, you get the balance where you expect the date, and vice versa. Your "date" column suddenly contains AED amounts, and your amount parsing fails silently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Detect document direction first. We check the dominant text alignment in the header rows. If the majority of header cells are right-aligned, we mirror our column index mapping before extraction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mixed-Direction Documents
&lt;/h2&gt;

&lt;p&gt;UAE bank statements often contain both Arabic and English — Arabic for legal text and section headers, English for transaction descriptions and amounts. This creates mixed-direction paragraphs that confuse naive extraction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simplified direction detection
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;detect_dominant_direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_text_blocks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rtl_chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;page_text_blocks&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\u0600&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\u06FF&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ltr_chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;page_text_blocks&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isascii&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isalpha&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rtl&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rtl_chars&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ltr_chars&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ltr&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Merchant Names: Arabic vs Transliterated
&lt;/h2&gt;

&lt;p&gt;This was the real surprise. UAE bank statements frequently show merchant names in two formats depending on whether the merchant registered with the bank in Arabic or English:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arabic text: actual Arabic script for the merchant name&lt;/li&gt;
&lt;li&gt;Transliterated: Arabic merchant name written in Latin characters (e.g., "MAKTABAT AL JARIR" for a bookstore)&lt;/li&gt;
&lt;li&gt;English: international merchant names in English&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For categorization, you need to handle all three. We built a lookup table that maps known UAE merchants in all three formats to categories. It's manual work — there's no clean automated way to do this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Date Format Variations
&lt;/h2&gt;

&lt;p&gt;Arabic dates in UAE bank statements come in at least 4 formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DD/MM/YYYY (most common)&lt;/li&gt;
&lt;li&gt;DD-MMM-YYYY with English month abbreviations
&lt;/li&gt;
&lt;li&gt;DD-MMM-YYYY with Arabic month names&lt;/li&gt;
&lt;li&gt;Hijri calendar dates (rare, but present in some government-linked banks)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We process Hijri dates using the &lt;code&gt;hijri-converter&lt;/code&gt; Python library. Miss this and you'll silently drop transactions or misparse dates by ~600 years.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Works
&lt;/h2&gt;

&lt;p&gt;After months of edge cases, our pipeline for Arabic UAE statements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract raw text with PyMuPDF (better RTL handling than pdfplumber for Arabic)&lt;/li&gt;
&lt;li&gt;Detect dominant direction per page&lt;/li&gt;
&lt;li&gt;Apply mirrored column mapping if RTL&lt;/li&gt;
&lt;li&gt;Normalize merchant names through Arabic → Latin transliteration&lt;/li&gt;
&lt;li&gt;Attempt date parsing in all 4 formats, cascade until one succeeds&lt;/li&gt;
&lt;li&gt;Fall back to OCR (AWS Textract) if text extraction confidence is low&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Banks we support well now: ENBD, ADCB, Mashreq, FAB, DIB, RAK Bank.&lt;/p&gt;

&lt;p&gt;If you're parsing UAE bank statements and hitting edge cases, drop a comment — happy to share more specifics.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; is a PDF bank statement analyzer supporting 8 languages including Arabic. First analysis free.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>arabic</category>
      <category>fintech</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I analyzed 500+ bank statements. Here's what I found.</title>
      <dc:creator>FLOW by Vestelon</dc:creator>
      <pubDate>Fri, 19 Jun 2026 07:32:42 +0000</pubDate>
      <link>https://dev.to/vestelonflow/i-analyzed-500-bank-statements-heres-what-i-found-2bah</link>
      <guid>https://dev.to/vestelonflow/i-analyzed-500-bank-statements-heres-what-i-found-2bah</guid>
      <description>&lt;h1&gt;
  
  
  I Analyzed 500+ Bank Statements. Here's What I Found.
&lt;/h1&gt;

&lt;p&gt;Over the past few months, while building &lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; — a PDF bank statement analyzer — we processed hundreds of anonymized bank statements from beta users across Europe, the Middle East, and Southeast Asia.&lt;/p&gt;

&lt;p&gt;The patterns were surprising. Here's what the data showed:&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding #1: The Average Person Has 3 Forgotten Subscriptions
&lt;/h2&gt;

&lt;p&gt;Not "maybe has." Has. Reliably, across different income levels and countries.&lt;/p&gt;

&lt;p&gt;The most common culprits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Software tools&lt;/strong&gt; from a job they left (Notion, Figma, Slack paid plans)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming services&lt;/strong&gt; with annual billing they forgot about&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free trials&lt;/strong&gt; that converted to paid (average: 2.1 per person)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insurance&lt;/strong&gt; for devices they no longer own&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Average value: &lt;strong&gt;€94-€158/month&lt;/strong&gt; depending on income level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding #2: High-Income Users Leak More
&lt;/h2&gt;

&lt;p&gt;Counter-intuitive, but: the higher the income, the more money is "leaking."&lt;/p&gt;

&lt;p&gt;Reason: lower financial stress → less attention to individual line items → more small charges slip through unnoticed.&lt;/p&gt;

&lt;p&gt;People earning €8k+/month often have 5-8 forgotten subscriptions vs 1-2 for people earning €2k/month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding #3: Expats Have 2-3x More Complexity
&lt;/h2&gt;

&lt;p&gt;Users with accounts in multiple countries (common for expats in UAE, UK, Singapore, Germany) had significantly more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicate services active in two countries&lt;/li&gt;
&lt;li&gt;Currency conversion fees adding up to €50-200/month&lt;/li&gt;
&lt;li&gt;Old direct debits from a previous country of residence still running&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the problem &lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; was originally built to solve — seeing across all your bank PDFs in one place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding #4: The "Harajuku Moment" for Finance
&lt;/h2&gt;

&lt;p&gt;Most people don't seek out financial tools until a trigger event:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Preparing for mortgage application&lt;/li&gt;
&lt;li&gt;First month with a big salary decrease or job loss&lt;/li&gt;
&lt;li&gt;Seeing a surprisingly high statement total&lt;/li&gt;
&lt;li&gt;Moving countries and having to "reset" finances&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building for this trigger matters more than building for "everyone who has money."&lt;/p&gt;

&lt;h2&gt;
  
  
  How FLOW Works
&lt;/h2&gt;

&lt;p&gt;Upload your bank statement PDFs → it extracts every transaction using OCR → categorizes them → finds patterns and anomalies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports 8 languages and 50+ bank formats&lt;/li&gt;
&lt;li&gt;Works with ENBD, Mashreq, ADCB (UAE), Barclays, HSBC, NatWest (UK), Deutsche Bank, Sparkasse (DE), SBI (IN), and more&lt;/li&gt;
&lt;li&gt;First analysis free, no card required&lt;/li&gt;
&lt;li&gt;No bank login or Open Banking connection needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building something in fintech or personal finance, happy to share more about what we've learned from parsing international bank PDF formats (it's... not fun, but doable).&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Data is anonymized and aggregated from opt-in beta users. Individual values vary significantly by country and income.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>personalfinance</category>
      <category>startup</category>
      <category>data</category>
    </item>
    <item>
      <title>How expats in Dubai (and the Gulf) are losing money without knowing it</title>
      <dc:creator>FLOW by Vestelon</dc:creator>
      <pubDate>Fri, 19 Jun 2026 07:32:14 +0000</pubDate>
      <link>https://dev.to/vestelonflow/how-expats-in-dubai-and-the-gulf-are-losing-money-without-knowing-it-2i3</link>
      <guid>https://dev.to/vestelonflow/how-expats-in-dubai-and-the-gulf-are-losing-money-without-knowing-it-2i3</guid>
      <description>&lt;h1&gt;
  
  
  How Expats in Dubai Are Losing Money Without Knowing It
&lt;/h1&gt;

&lt;p&gt;If you're an expat living in Dubai (or anywhere in the Gulf), you probably have bank accounts in at least two countries. Maybe three.&lt;/p&gt;

&lt;p&gt;UAE account for your salary. A UK, German, or Indian account back home. Maybe a third somewhere for savings or family transfers.&lt;/p&gt;

&lt;p&gt;And every month, money slips through the cracks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem No One Talks About
&lt;/h2&gt;

&lt;p&gt;When you live across multiple financial systems, your expenses become invisible. You can't see the full picture from any single banking app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forgotten subscriptions still charging your UK card&lt;/li&gt;
&lt;li&gt;Currency conversion fees eating 2-3% on every transfer
&lt;/li&gt;
&lt;li&gt;Duplicate services in two countries (Netflix UAE + Netflix UK somehow active)&lt;/li&gt;
&lt;li&gt;Insurance you cancelled that's still being charged&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most expats I've talked to are shocked when they actually analyze all their statements together.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;FLOW&lt;/a&gt; is a PDF bank statement analyzer. You upload your bank PDFs — from any country, any language — and it categorizes every transaction, finds patterns, and shows you exactly what you're spending and where.&lt;/p&gt;

&lt;p&gt;It supports &lt;strong&gt;8 languages&lt;/strong&gt;: English, Arabic, German, French, Spanish, Slovak, Czech, and Hungarian. Useful if your UAE bank statement is in Arabic and your home country one is in another language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No bank login required.&lt;/strong&gt; You just upload the PDF. It works with ENBD, ADCB, Mashreq, HSBC UAE, Barclays UK, Deutsche Bank, SBI, and most other banks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Numbers That Surprised Users
&lt;/h2&gt;

&lt;p&gt;When we ran our first beta with expats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average &lt;strong&gt;€137/month&lt;/strong&gt; in forgotten or duplicate subscriptions found&lt;/li&gt;
&lt;li&gt;Average time to find: &lt;strong&gt;8 minutes&lt;/strong&gt; to upload and analyze&lt;/li&gt;
&lt;li&gt;Most common finding: subscription services active in home country still running&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who It's For
&lt;/h2&gt;

&lt;p&gt;FLOW works well for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dubai/UAE expats&lt;/strong&gt; managing accounts in 2+ countries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Finance professionals&lt;/strong&gt; who review client bank data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small business owners&lt;/strong&gt; wanting clear expense visibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anyone&lt;/strong&gt; getting ready for a mortgage application who needs to understand their own spending&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It Free
&lt;/h2&gt;

&lt;p&gt;First analysis is free, no card required: &lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;vestelonflow.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're an expat with PDF bank statements from multiple countries, I'd genuinely love to hear if it helps — and what it misses. Still adding banks and improving categorization.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Python, AWS Textract, and a lot of edge cases from international bank formats.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>expat</category>
      <category>fintech</category>
      <category>personalfinance</category>
      <category>dubai</category>
    </item>
    <item>
      <title>How I built a PDF bank statement analyzer in 8 languages (and what I learned)</title>
      <dc:creator>FLOW by Vestelon</dc:creator>
      <pubDate>Thu, 18 Jun 2026 20:16:07 +0000</pubDate>
      <link>https://dev.to/vestelonflow/how-i-built-a-pdf-bank-statement-analyzer-in-8-languages-and-what-i-learned-3580</link>
      <guid>https://dev.to/vestelonflow/how-i-built-a-pdf-bank-statement-analyzer-in-8-languages-and-what-i-learned-3580</guid>
      <description>&lt;p&gt;I spent months building FLOW (&lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;vestelonflow.com&lt;/a&gt;) — a tool that analyzes bank statement PDFs and finds forgotten subscriptions, hidden fees, and recurring charges.&lt;/p&gt;

&lt;p&gt;Here's what I learned building it in 8 languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Most personal finance apps require you to connect your bank account. For many people (especially in Europe), that's a dealbreaker. GDPR concerns, privacy fears, and simply not trusting third-party apps with banking credentials.&lt;/p&gt;

&lt;p&gt;My insight: &lt;strong&gt;the data people need is already in their PDF bank statements.&lt;/strong&gt; Every bank generates them. Most people never look past the total.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;The core flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User uploads PDF bank statement&lt;/li&gt;
&lt;li&gt;PDF text extraction (pdfplumber + fallback OCR)&lt;/li&gt;
&lt;li&gt;Transaction parsing — this is the hard part&lt;/li&gt;
&lt;li&gt;LLM categorization pipeline&lt;/li&gt;
&lt;li&gt;Subscription detection (recurring charges with same merchant)&lt;/li&gt;
&lt;li&gt;Report generation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The trickiest part was transaction parsing. Every bank formats their PDF differently. German banks look nothing like Slovak banks. We ended up building bank-specific parsers for the most common formats and a fallback generic parser.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 8-Language Challenge
&lt;/h2&gt;

&lt;p&gt;Supporting Slovak, Czech, German, French, Spanish, Polish, Arabic, and Chinese wasn't just about translating the UI. The financial terminology varies significantly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Permanent order" in English = "Trvalý príkaz" in Slovak = "Dauerauftrag" in German&lt;/li&gt;
&lt;li&gt;Subscription detection keywords differ by region&lt;/li&gt;
&lt;li&gt;Date/amount formats are locale-specific&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We ended up with language-specific merchant dictionaries for common subscription services in each market.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Matters
&lt;/h2&gt;

&lt;p&gt;The biggest lesson: &lt;strong&gt;people don't want a budgeting dashboard. They want a specific, actionable number.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"You're spending €137/month on forgotten subscriptions" converts. "Your spending breakdown by category" does not.&lt;/p&gt;

&lt;p&gt;The product is live at &lt;a href="https://vestelonflow.com" rel="noopener noreferrer"&gt;vestelonflow.com&lt;/a&gt; — first report is free, no card required, no bank connection needed.&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the PDF parsing approach, the LLM pipeline, or the localization challenges.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>python</category>
      <category>showdev</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
