# Vibecoded: Automating Instapaper → Beeminder with Playwright (Daily, Headless, Reliable)

**URL:** <https://forum.beeminder.com/t/vibecoded-automating-instapaper-beeminder-with-playwright-daily-headless-reliable/12816>\
**Category:** Akrasia\
**Created:** [August 3, 2026, 1:09pm UTC](https://forum.beeminder.com/t/vibecoded-automating-instapaper-beeminder-with-playwright-daily-headless-reliable/12816 "2026-08-03T13:09:17Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![mad](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.beeminder.com/mad/32/4275_2.png) [@mad](https://forum.beeminder.com/u/mad)\
**Post date:** [August 3, 2026, 1:09pm UTC](https://forum.beeminder.com/t/vibecoded-automating-instapaper-beeminder-with-playwright-daily-headless-reliable/12816/1 "2026-08-03T13:09:17Z")

</div>

**What this script does:** looks at the number of unread items on your instapaper queue and then sends it to beeminder

**Use cases:**

- (mine) people like me who want to whittle down their backlog (172 at the moment, thanks for asking)
- people who want to beemind net articles per day (probably a way to vibe code something to work out how many articles you read each day too)
- others???

\*\*\*

Okay so I struggled with the instapaper/pocket backlog counting stuff and I decided to vibecode it, and it seems to have turned out REALLY well so thought I’d share it here. I don’t really understand anything I did, but it took a lot of time (because, obviously, vibecoding is tricky and a previous version recently stopped working because instapaper changed their interface).

I enhanced it this time to automatically upload the results to beeminder (requires your API token).

I haven’t tested the automation, but I figure I’ll forget to post this if I wait for it to successfully automate, so… (the test run worked fine though).

Anyway see below for the robot’s explanation of what it did and how to set it up - I can vouch for this procedure seeming to include all the steps of the iteration that actually worked.

_This post was written by Microsoft Copilot at my request:_

> **Copilot's post**
>
> Hi everyone! I wanted to share a complete, step‑by‑step guide for automatically sending your Instapaper unread count to Beeminder every day. This setup uses Playwright (a browser automation tool), a persistent Firefox profile so you only log in once, and Windows Task Scheduler to run it daily in headless mode.
> 
> If you want a “track my Instapaper backlog automatically” goal, this is a fully working solution.
> 
> # **What this setup does**
> 
> - Opens Instapaper in a headless browser
> 
> - Reads the unread count directly from the sidebar
> 
> - Uploads that number to Beeminder
> 
> - Runs automatically every day
> 
> - Requires no manual login after the first run
> 
> - Works even with Instapaper’s new React interface
> 
> # **Prerequisites**
> 
> You’ll need:
> 
> - Windows
> 
> - Python 3
> 
> - Playwright
> 
> - A Beeminder goal
> 
> - Your Beeminder auth token
> 
> # **1. Install Playwright**
> 
> Open PowerShell and run:
> 
> Code
> 
> ```auto
> pip install playwright
> playwright install
> 
> ```
> 
> This installs the Python bindings and the Firefox browser Playwright uses.
> 
> # **2. Create the Python script**
> 
> Create a file named:
> 
> Code
> 
> ```auto
> count_unread_playwright.py
> 
> ```
> 
> Paste this entire script into it:
> 
> python
> 
> ```auto
> from playwright.sync_api import sync_playwright
> import os
> import requests
> import time
> import json
> 
> PROFILE_DIR = "instapaper_profile"
> SESSION_FILE = "instapaper_sessionstorage.json"
> 
> # ---- Beeminder settings ----
> BEEMINDER_USER = "YOUR BEEMINDER USERNAME"
> BEEMINDER_TOKEN = "YOUR BEEMINDER TOKEN"
> BEEMINDER_GOAL = "YOUR BEEMINDER GOAL SLUG"
> # ----------------------------
> 
> def beeminder_upload(value):
> payload = {
> "auth_token": BEEMINDER_TOKEN,
> "value": value,
> "measured_at": int(time.time()),
> "comment": "Instapaper unread count"
> }
> 
> url = f"https://www.beeminder.com/api/v1/users/{BEEMINDER_USER}/goals/{BEEMINDER_GOAL}/datapoints.json"
> r = requests.post(url, data=payload)
> 
> if r.status_code == 200:
> print(f"[BEEMINDER] Uploaded {value}")
> else:
> print(f"[BEEMINDER] Error {r.status_code}: {r.text}")
> 
> def save_sessionstorage(page):
> data = page.evaluate("JSON.stringify(sessionStorage)")
> with open(SESSION_FILE, "w") as f:
> f.write(data)
> print("[DEBUG] Saved sessionStorage")
> 
> def restore_sessionstorage(page):
> if os.path.exists(SESSION_FILE):
> with open(SESSION_FILE, "r") as f:
> data = f.read()
> page.evaluate(f"""
> const obj = JSON.parse('{data}');
> for (const key in obj) {{
> sessionStorage.setItem(key, obj[key]);
> }}
> """)
> print("[DEBUG] Restored sessionStorage")
> 
> def get_unread_count(page):
> print("[DEBUG] Waiting for unread count element…")
> page.wait_for_selector("span.side-nav-count", timeout=15000)
> 
> count_text = page.inner_text("span.side-nav-count")
> count = int(count_text.strip())
> 
> print(f"[DEBUG] Unread count: {count}")
> return count
> 
> with sync_playwright() as p:
> if not os.path.exists(PROFILE_DIR):
> os.makedirs(PROFILE_DIR)
> 
> browser = p.firefox.launch_persistent_context(PROFILE_DIR, headless=True)
> 
> page = browser.pages[0]
> 
> print("Opening Instapaper…")
> page.goto("https://www.instapaper.com/u")
> 
> restore_sessionstorage(page)
> page.reload()
> 
> if "login" in page.url.lower():
> print("\nYou are not logged in yet.")
> print("Log in manually in the browser window.")
> input("Press Enter here once you're fully logged in…")
> save_sessionstorage(page)
> else:
> print("\nSession detected — already logged in.")
> 
> total = get_unread_count(page)
> print(f"\nTotal unread count: {total}")
> 
> beeminder_upload(total)
> 
> browser.close()
> 
> ```
> 
> ### What this script does
> 
> - Loads Instapaper using a persistent Firefox profile
> 
> - Restores sessionStorage so you stay logged in
> 
> - Reads the unread count from the sidebar (`span.side-nav-count`)
> 
> - Uploads it to Beeminder
> 
> - Runs headlessly (no visible browser window)
> 
> # **3. Run the script once manually**
> 
> Run:
> 
> Code
> 
> ```auto
> python count_unread_playwright.py
> 
> ```
> 
> If it asks you to log in:
> 
> - A Firefox window will appear
> 
> - Log into Instapaper normally
> 
> - Press Enter in the terminal
> 
> - Your session will be saved permanently
> 
> After that, the script will run headless and won’t ask again.
> 
> # **4. Create a** `.bat` **launcher for automation**
> 
> Create:
> 
> Code
> 
> ```auto
> run_instapaper.bat
> 
> ```
> 
> Put this inside:
> 
> Code
> 
> ```auto
> cd /d C:\Users\<YOUR USERNAME>\[YOUR SAVE DIRECTORY]
> python count_unread_playwright.py
> 
> ```
> 
> Adjust the path if your script lives somewhere else.
> 
> # **5. Schedule it daily with Windows Task Scheduler**
> 
> 1. Open **Task Scheduler**
> 
> 2. Click **Create Task…**
> 
> 3. **General tab**
> 
> 4. **Triggers tab**
> 
> 5. **Actions tab**
> 
> 6. **Settings tab**
> 
> Click OK, enter your password, and you’re done.
> 
> # **6. Confirm it works**
> 
> Right‑click the task → **Run**.
> 
> You should see:
> 
> - The script runs silently
> 
> - The unread count prints in the Task Scheduler history
> 
> - A datapoint appears in Beeminder
> 
> After that, it will run automatically every day.
> 
> # **Final Notes**
> 
> - This setup is robust against Instapaper UI changes because it reads the sidebar count directly.
> 
> - You only log in once; sessionStorage keeps you authenticated.
> 
> - Playwright’s persistent Firefox profile makes the whole thing stable and low‑maintenance.
> 
> Hope this helps someone else automate their reading backlog!
