Skip to content

Fix: empty get-my-articles + repeated logins (session persistence, Cloudflare, wrong stories tab) #1

Description

@emregulerr

Summary

get-my-articles (and the other authenticated tools) return empty results, and the user is forced to log in on almost every run. While debugging this I found it is actually several overlapping issues in the browser automation layer. I have a fix ready and will open a PR that references this issue.

Symptoms

  • A Chromium window opens on (almost) every call instead of staying in the background.
  • Re-login is required repeatedly even though a session was "saved".
  • login-to-medium reports success, but the next tool call still behaves as logged-out.
  • get-my-articles returns [] even when the account has published stories.

Root causes (verified empirically)

  1. Session cookies are lost across context restarts. Medium's auth relies on session cookies (sid, xsrf). A persistent profile keeps cookies with an expiry, but Chromium drops pure session cookies when the context is closed/reopened — so the headed→headless switch (and server restarts) silently log the user out. (Reproduced with a minimal persistent-context add/close/reopen test.)
  2. Cloudflare bot challenge blocks headless navigation. Medium serves a "Just a moment…" interstitial. The code never waits it out, so extraction runs against the challenge page. It is also made worse by a User-Agent mismatch: the visible login uses a normal "Chrome" UA while headless reports "HeadlessChrome", which invalidates the cf_clearance cookie and re-triggers the challenge.
  3. Wrong stories URL. get-my-articles navigates to https://medium.com/me/stories/public, which now redirects to the Drafts tab. The published list lives at https://medium.com/me/stories?tab=posts-published.
  4. Login is detected from cookie presence only. Medium sets uid/sid for anonymous visitors too, so sid+uid is not proof of authentication — the page renders logged-out while the code thinks it is logged in.
  5. Outdated selectors for the stories list.

Proposed fix (in the upcoming PR)

  • Persistent Chrome profile plus a full storageState snapshot that is re-injected on every launch (carries session cookies through the headed→headless switch and across restarts).
  • A fixed, consistent User-Agent for both login and headless runs, and an explicit Cloudflare "Just a moment…" wait after each navigation.
  • Correct published-tab URL and more robust extraction.
  • Auth detected from the actual page (absence of the header Sign-in button), not cookie presence.
  • Headless-by-default background operation; the visible window appears only for the one-time login.

Notably this also fixes the documented "Google login session" limitation

The README notes Google login sessions couldn't be persisted. With the persistent profile + storageState re-seeding, a Google login is captured and reused silently in the background (verified end-to-end: get-my-articles returns all published stories headless, no window, no re-login).

Environment

  • Playwright bundled Chromium 138
  • Windows 10/11, Node.js
  • Medium web (mid-2026 layout)

Thanks for the browser-based rewrite — happy to adjust the PR to your preferences.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions