Fetching Incoming Invoices in an Automated Fashion With Puppeteer

Home » Blog » Business » Fetching Incoming Invoices in an Automated Fashion With Puppeteer

Like I said in 2016, accounting is still a manual and tedious process.

However, since then I’ve made quite some headway, especially with regard to automatically fetching and storing incoming invoices. By now, all of those thankfully arrive via email, which allows me to have Zapier automatically fetch them and store attached invoice PDFs in the appropriate folders in Google Drive.

One particular, lasting pet peeve of mine in that respect, however, so far has been German railway company Deutsche Bahn AG and the fairly limited and inaccessible (by automated means, that is) way by which they’re giving you access to your invoices. For some convoluted, bureaucratic reason I didn’t fully comprehend they can’t – or won’t – automatically send you invoices for regional train tickets bought online or via their mobile app. All you get is a purchase confirmation email, which doesn’t include the actual invoice. You have to sign in to their online ticket store instead and manually go through a 3-step process for each ticket in order to have an email with the invoice sent to you.

So, there I was. Regularly logging in to the Deutsche Bahn ticket store at the end of each month in order to manually trigger invoice delivery for up to 30 tickets during a busy month with plenty of client meetings and on-site consulting. Triggering the download for each of my public transport invoices for keeping track of my travel expenses so far has been a tedious, recurring monthly task.

Since last week however, I’m using Puppeteer, a popular Node.js library that allows you to programmatically control a Chromium browser in order to access websites in an automated fashion with a bespoke robotic process automation workflow for fetching these invoices.

To that effect, I’ve created and published a small Node.js command line tool called InvoiceFetcher that allows me (and you if you’re having the same or a similar problem) to finally automate this process.

Together with 1Password‘s command-line tool (for not having to store my Deutsche Bahn credentials in plain text somewhere, or alternatively having to remember them) and the tiny Bash script below all I have to do now by the end of each month is to execute a single command, which then automatically takes care of logging into the online store and triggering an invoice email for each ticket.

If you’re wondering where those text files in ~/Google\ Drive/Accounting/db_invoice_numbers come from that get concatenated to db_invoice_numbers.txt: This is where the purchase confirmation email mentioned above comes in handy. Again, I’m using Zapier to have a text file containing the invoice number created for each such confirmation email.

In order to install and use InvoiceFetcher all you have to do is clone the repository and then run npm link in the project’s root folder. This will create a symlink to the main index.js script under the name invoice-fetcher in your global node_modules folder, which in turn will allow you to run the invoice-fetcher command from anywhere on your machine.

Afterwards, you can simply run

invoice-fetcher $DB_USERNAME $DB_PASSWORD $DB_INVOICE_NUMBERS

in order for InvoiceFetcher to retrieve the Deutsche Bahn invoices specified by whitespace-delimited invoice numbers under $DB_INVOICE_NUMBERS.

The reason why I didn’t publish InvoiceFetcher as a fully-fledged NPM package that can be installed via npm install yet is that – while enormously useful to me – InvoiceFetcher so far is more of a one-off script that I didn’t want to pollute the official NPM repository with.

If you have any questions about the particulars of these Zapier processes (or “Zaps” as they like to call them) or any of the components and scripts involved in this process automation please get in touch.


#!/usr/bin/env bash

eval $(op signin)

cd ~/Google\ Drive/Accounting/db_invoice_numbers
cat *.txt > ../db_invoice_numbers.txt

db_invoice_numbers=''
while read db_invoice_number; do
  db_invoice_numbers+=" ${db_invoice_number}"
done < ~/Google\ Drive/Accounting/db_invoice_numbers.txt

invoice-fetcher $(op get item ITEM_KEY --fields username) $(op get item ITEM_KEY --fields password) $db_invoice_numbers

rm *.txt

Update 23/10/2020: The project has been renamed to InvoiceRobot.

About the author: Bjoern
Independent IT consultant, entrepreneur
One comment

    Leave a Comment