Urgent.News

What's breaking now, across thousands of outlets.

Tech

Parsing bank statement PDFs in the browser, with a CSP that proves nothing gets uploaded

People who freelance often can't get a CSV out of their bank. Some banks only give PDF statements, others limit downloads to 90 days, and a few dropped CSV and QFX exports entirely. But every bookkeeping spreadsheet wants rows of Date, Description, Amount . The usual fix is an online converter, which means uploading a year of bank statements to a stranger's server. I didn't want to ask anyone to…

Freelancers often struggle to obtain CSV files from their banks. Some institutions only provide PDF statements, impose 90-day download limits, and have abandoned CSV and QFX exports altogether. Nonetheless, every bookkeeping spreadsheet requires rows containing Date, Description, and Amount. The typical solution involves an online converter, which necessitates uploading years' worth of bank statements to a third-party server.

This converter, built for Paid & Filed, operates entirely within a web browser tab: paidandfiled.com/bank-statement-converter. This article delves into the three most challenging aspects of the project.

1. Converting PDF.js text runs into lines. The page.getTextContent() function does not yield lines; instead, it provides text runs, each with a transform matrix and in the order the PDF generator wrote them. A single statement row like "03-14 ACH DEPOSIT CLIENT CO 1,250.00 4,310.27" may be presented as six runs, out of sequence, with the minus sign of a debit split into its own run.

Consequently, the initial step involves rebuilding lines geometrically: sorting by baseline (transform[5], top to bottom), then x position, grouping runs whose baselines are within 2 points, and joining runs that physically touch without a space, ensuring words split by pdf.js remain intact. The function itemsToLines() implements this logic, returning an array of strings.

2. Developing a single reader capable of handling various bank formats. The initial approach was to create a template for each bank. However, this design proved impractical as the same bank's layout could vary between checking and savings accounts, between years, and between web and mailed PDFs. The generic rule proved to be straightforward.

A transaction line begins with a date and concludes with one or two amounts; the latter is the running balance. Everything in between constitutes the description. Dates can appear as "03/14," "03-14," "Mar 14," or "14 Mar 2026," and when a row lacks a year, it originates from the statement period indicated in the header, accounting for December statements that extend into January.

The most challenging aspect pertains to determining the sign. Bank PDFs express direction in at least five ways: separate debit and credit columns (which merge into one column once the page is flattened into text), a trailing minus (45.10-), CR and DR codes, section headings like "Deposits and other credits," or the absence of any indication. Therefore, direction is prioritized in the following order: let direction be "in" or "out."

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Turning one TypeScript CardSpec into 49 static palette PNGs

Belle AI (aicoloranalysis.io) publishes downloadable color-palette cards: one for each of the twelve sub-seasons and four parent seasons, plus cards for 20 celebrity pages and 13 "color analysis for…

  • Belle AI generates 49 static palette PNGs from one CardSpec
  • CardSpec shape defines common structure for all cards
  • Route handler creates static parameters for all 49 cards

Making a calculator other sites can embed, on a fully static site

I run a small site for freelancers, Paid & Filed , and its most useful page is a free 1099 tax calculator that works out quarterly estimated tax.

  • Calculator embedded via React component
  • Embed route excludes header, footer, analytics
  • Height adjustment script for seamless display

Implement Training File Export with Temporary Downloads (Presigned URLs, Retention)

The constraint that changes this design is large-file throughput. An education platform should keep export bytes off its application workers, issue a short-lived download URL only after authorization…

  • Implement export as immutable object with signed GET request URL.
  • Record timestamps and policy selection for reproducible audits.
  • Use storage service for large data path, API for control-plane job.

Exit codes in CI: what every number means and how to fix it

Exit codes in CI are the only thing a failed step gets to say about itself, which is why so much of debugging a pipeline comes down to reading one number.

  • Exit codes indicate success (0) or failure in CI pipelines
  • 0 means successful completion, others are convention-based
  • Bash reserves 127 (missing command) and 126 (executable issue)

More from Sunday 15 November →