Automating My Library's Newspaper Pass

Automating My Library's Newspaper Pass
Photo by AbsolutVision / Unsplash

My local library gives cardholders free access to the Boston Globe. The catch is that the pass only lasts 72 hours.

So every three days I was repeating the same steps: open the library's "Connect to..." page, type in a 14-digit card number, land on a Globe registration form, re-enter my name, email and password, and click a button labeled "Create Account" for an account I already had. The library's page is upfront about it:

At the end of your free temporary access period, simply complete this form again.

Same steps, same interval, no judgement required. That is the kind of thing I would rather hand to a container.

Not every paper is worth automating

My library offers several papers through the same connector, and I originally planned to automate all of them. Before writing any code I replayed each flow by hand to see what the library was actually handing out. That saved me from building four things that would not have worked.

  • Boston Globe: a rolling 72-hour entitlement attached to an account I own.
  • New York Times: a static gift code, redeemed once against my NYT login.
  • Wall Street Journal: a static partner redemption link.
  • Washington Post: a static special-offer sign-in link.
  • Eagle Tribune (NewsBank): a throwaway browsing session, with no account behind it.

Only the Globe is on a clock. The other three papers give you a one-shot code that you redeem once against your own login, so running that on a schedule does nothing at all. The NewsBank titles do not even have an account attached: you enter your card, you get a browsing session, and when you close the tab it is gone.

The useful question turned out not to be "how do I automate this", but "which of these is actually a renewal". Four of the five looked automatable from the outside and were not. A scheduler pointed at them would have run indefinitely without accomplishing anything.

The flow is two form posts

I assumed this would need a headless browser. It does not, which is worth checking before reaching for Playwright.

The whole chain is two HTTP requests:

  1. POST the card number to the library's connector. A valid card returns a 302 to the newspaper's registration page. An invalid one returns a 200 with a visible error message, which makes failure easy to detect.
  2. POST the registration form. This is an ASP.NET WebForms page, so you have to echo back the hidden fields the server just gave you (__VIEWSTATE, __VIEWSTATEGENERATOR, __EVENTVALIDATION) along with your name, email and password. Success is a 302 off the registrar and onto the newspaper's own site.

No JavaScript, no CAPTCHA, nothing that needs a browser. So the whole service is a bit of Python using requests, which is cheaper to run and has a lot less to break than a browser in a container.

One thing I did not expect: submitting "Create Account" for an account that already exists is the intended path. It does not error, and it does not reset your password. It just extends the entitlement, which is what you are doing manually anyway.

How it works

The service wakes up on a schedule and asks one question per newspaper: is this due?

  1. Renew early. The window is 72 hours, but it renews every 24. That leaves about two days of retries before access would actually lapse. If the library is down or the site is slow, nothing is urgent, it just tries again in 30 minutes.
  2. Track expiry, not just success. It stores when the current pass runs out, so restarting the container does not trigger an unnecessary renewal.
  3. Fail loudly when the form changes. If the newspaper changes their registration form, the service errors with the exact fields it expected and could not find. The alternative is finding out days later when the paywall comes back.
  4. Keep the extras optional. Publishing to Home Assistant, sending alerts and pinging a monitor are all best effort. A dead MQTT broker logs a warning, it does not fail the renewal.
  5. Papers are config, not code. Providers live in a providers.json with two modes: ez_register for real renewals, and link_only for the one-shot codes, which just surfaces the current redemption URL. Adding a paper is a config change.

Home Assistant

Since it is already running, it publishes over MQTT discovery, with one device per newspaper:

  • sensor.boston_globe_access_expires is a timestamp sensor, so the UI shows "in 2 days"
  • binary_sensor.boston_globe_access_active is on or off
  • sensor.boston_globe_access_status is ok or failed, with the last message and failure count as attributes

The automation actually worth setting up is an alert when binary_sensor.*_access_active has been off for an hour. That means several renewals failed in a row, which in practice means the library card expired, and no amount of retrying fixes that.

Getting started

It is a container with a handful of environment variables: your card number and your existing newspaper login.

cp .env.example .env
docker compose up -d --build

There is a status page showing each paper's state and expiry, a /health endpoint for monitoring, and a POST /run if you want to force a renewal. Credentials are read from the environment and never stored in the repo.

The code is on GitHub at dimatx/library-news-access. The repo also has a FINDINGS.md documenting what each newspaper hands out and why only one of them is automated, mostly so I do not try to "fix" the other four in six months.

It is a small automation, but it replaced something I'd need to do over and over.