DEV Community

Shlok Shah
Shlok Shah

Posted on

How I Automated Claude’s 5-Hour Usage Window with Cloudflare Workers & Puppeteer

I Automated Claude’s 5-Hour Usage Window with Cloudflare Workers

I got tired of manually sending a message to Claude just to start its 5-hour rolling usage window.

So I automated it.

Not with a VPS.

Not with a browser running 24/7.

With a Cloudflare Worker, Browserless, and Puppeteer.

The result is Claude Pinger — a small serverless service that periodically opens Claude, authenticates an account, navigates to a dedicated conversation, and sends a minimal ping.

GitHub: https://github.com/shlokkokk/claude-pinger


The problem

Claude uses a rolling 5-hour usage window.

The part that bothered me was that the window doesn't start counting down until the account actually sends a message.

If you're not actively using Claude, nothing happens.

So if I wanted the window to be active before I started working, I had to remember to manually open Claude and send something.

That's exactly the kind of repetitive task I prefer to automate.

The requirements were straightforward:

  • Run automatically every 5 hours
  • Work without a local machine
  • Support multiple accounts
  • Reuse the same conversation
  • Keep token usage extremely small
  • Store credentials securely
  • Survive browser-navigation failures
  • Allow manual execution for testing

That led to this architecture.


Architecture

┌──────────────────────────┐
│      Cloudflare Cron     │
│        Every 5 hours     │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│     Cloudflare Worker    │
│       Orchestration      │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│        Browserless       │
│    Remote Browser API    │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│        Puppeteer         │
│     Browser Automation   │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│         Claude.ai        │
│                          │
│  "ping. Reply with '.'   │
│           only."         │
└────────────┬─────────────┘
             │
             ▼
            "."
Enter fullscreen mode Exit fullscreen mode

Each component has one job:

Component Responsibility
Cloudflare Cron Decides when the automation runs
Cloudflare Worker Orchestrates the execution
Browserless Provides the remote browser
Puppeteer Controls the browser
Claude.ai Receives the ping
Worker Secrets Stores credentials

The Worker wakes up, performs the automation, and finishes.

There is no reason to keep a browser process alive between executions.


Why Browserless?

Cloudflare Workers aren't designed to run a full browser themselves.

I still wanted the Worker to be responsible for scheduling and orchestration, though.

So the Worker calls Browserless, which provides the remote browser environment.

That gives the project a clean separation:

Cloudflare
    │
    │ schedule + orchestration
    ▼
Browserless
    │
    │ browser execution
    ▼
Puppeteer
    │
    │ interaction
    ▼
Claude.ai
Enter fullscreen mode Exit fullscreen mode

The Worker doesn't need to maintain a browser server.

It simply requests a browser session when the job runs.


The smallest useful ping

The automation doesn't need Claude to generate anything meaningful.

It only needs to send a message.

So the prompt is intentionally tiny:

ping. Reply with '.' only.
Enter fullscreen mode Exit fullscreen mode

The expected response:

.
Enter fullscreen mode Exit fullscreen mode

The idea is simple:

start the interaction while keeping the generated response as small as possible.

This isn't prompt engineering for better answers.

It's prompt engineering for a smaller answer.


Multiple accounts from one Worker

I didn't want to deploy one Worker per Claude account.

Claude Pinger can process multiple configured accounts during the same execution.

Conceptually:

                    Cloudflare Worker
                           │
             ┌─────────────┼─────────────┐
             │             │             │
             ▼             ▼             ▼
         Account 1      Account 2      Account 3
             │             │             │
             ▼             ▼             ▼
        Browserless    Browserless    Browserless
             │             │             │
             ▼             ▼             ▼
          Claude         Claude         Claude
Enter fullscreen mode Exit fullscreen mode

Additional accounts are configured through Worker Secrets:

wrangler secret put CLAUDE_SESSION_KEY_2
wrangler secret put CLAUDE_SESSION_KEY_3
Enter fullscreen mode Exit fullscreen mode

The same Worker can then process the configured accounts during its scheduled execution.


Don't create a new chat every time

Another problem was conversation clutter.

If the automation created a new conversation every five hours, the sidebar would eventually become:

Ping test
Ping test
Ping test
Ping test
Ping test
Ping test
...
Enter fullscreen mode Exit fullscreen mode

Instead, Claude Pinger can reuse a dedicated conversation.

For example:

Ping test
Enter fullscreen mode Exit fullscreen mode

A direct conversation URL can be configured with:

wrangler secret put CLAUDE_CHAT_URL_1
Enter fullscreen mode Exit fullscreen mode

That gives the automation a stable target instead of creating a new conversation every time.


Direct navigation isn't enough

This is where browser automation gets interesting.

A script that works once isn't necessarily a reliable automation system.

Claude Pinger supports two navigation paths.

1. Direct navigation

If a chat URL is configured:

CLAUDE_CHAT_URL_1
Enter fullscreen mode Exit fullscreen mode

the automation attempts to open it directly.

2. Fallback navigation

If direct navigation isn't available or fails, the automation can fall back to the recent chats interface and locate the configured conversation.

The logic is essentially:

             Start
               │
               ▼
       Chat URL available?
          /           \
        yes            no
         │              │
         ▼              ▼
    Open chat       Open recents
         │              │
         │              ▼
         │         Find conversation
         │              │
         └──────┬───────┘
                ▼
            Send ping
Enter fullscreen mode Exit fullscreen mode

This matters because unattended browser automation has to assume that things will occasionally fail.


The cron trigger

The Worker is scheduled using a Cloudflare Cron Trigger.

The configuration is:

{
  "name": "claude-pinger",
  "main": "src/index.js",
  "compatibility_date": "2024-01-01",
  "triggers": {
    "crons": ["0 */5 * * *"]
  }
}
Enter fullscreen mode Exit fullscreen mode

The execution lifecycle becomes:

        asleep
           │
           ▼
      cron fires
           │
           ▼
     Worker starts
           │
           ▼
   Browser automation
           │
           ▼
       Claude ping
           │
           ▼
     Worker finishes
           │
           ▼
        asleep
Enter fullscreen mode Exit fullscreen mode

That's the entire server-side lifecycle.


The hard part wasn't sending the message

Typing a message into a browser is easy.

Making that process run unattended is the actual engineering problem.

You have to account for:

  • Authentication state
  • Browser startup
  • Navigation timing
  • Dynamic UI elements
  • Existing conversations
  • Direct URL failures
  • Fallback navigation
  • Browser automation detection
  • Multiple accounts
  • Secret management
  • Scheduled execution
  • Failure reporting

A browser script that works perfectly while you're watching it is very different from one that needs to run by itself for weeks.

That's where most of the interesting work ended up.


Keeping credentials out of Git

Claude session keys are authenticated credentials.

They should never be hardcoded into the repository.

Claude Pinger uses Cloudflare Worker Secrets:

wrangler secret put BROWSERLESS_TOKEN

wrangler secret put CLAUDE_SESSION_KEY

wrangler secret put CLAUDE_SESSION_KEY_2
Enter fullscreen mode Exit fullscreen mode

Chat URLs can also be stored as secrets:

wrangler secret put CLAUDE_CHAT_URL_1
Enter fullscreen mode Exit fullscreen mode

This keeps credentials outside the source code.

Security note: Treat Claude session cookies like passwords. They provide authenticated access to an account. Never commit them, expose them in logs, or share them publicly.


Setup

Prerequisites

You'll need:

  • Node.js 18+
  • Cloudflare Wrangler
  • A Browserless API token
  • Claude account session key(s)

Install Wrangler:

npm install -g wrangler
Enter fullscreen mode Exit fullscreen mode

Clone the repository:

git clone https://github.com/shlokkokk/claude-pinger.git
cd claude-pinger
Enter fullscreen mode Exit fullscreen mode

Configure Browserless:

wrangler secret put BROWSERLESS_TOKEN
Enter fullscreen mode Exit fullscreen mode

Configure your primary Claude account:

wrangler secret put CLAUDE_SESSION_KEY
Enter fullscreen mode Exit fullscreen mode

Optional second account:

wrangler secret put CLAUDE_SESSION_KEY_2
Enter fullscreen mode Exit fullscreen mode

Optional direct chat URL:

wrangler secret put CLAUDE_CHAT_URL_1
Enter fullscreen mode Exit fullscreen mode

Then deploy:

wrangler deploy
Enter fullscreen mode Exit fullscreen mode

Manual execution

The cron trigger isn't the only way to run it.

You can manually execute the Worker:

curl -X POST https://<your-worker-subdomain>.workers.dev
Enter fullscreen mode Exit fullscreen mode

A successful execution returns information about the accounts processed:

{
  "message": "Multi-account ping finished!",
  "results": [
    {
      "account": "Account 1",
      "result": {
        "success": true,
        "url": "https://claude.ai/chat/...",
        "pageTitle": "Ping test - Claude",
        "actionExecuted": true,
        "stepError": null
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

That makes it much easier to test the automation before relying on the scheduled execution.


Why I think this is an interesting use of Workers

Cloudflare Workers are usually associated with APIs, middleware, edge functions, and lightweight web services.

This project uses them slightly differently.

The Worker is essentially acting as an automation orchestrator.

It doesn't run the browser itself.

It doesn't store application state.

It doesn't need a database.

It doesn't need a server running continuously.

It simply coordinates:

schedule → browser session → authentication → navigation → action → result

and then disappears.

That's a pretty useful pattern for small, event-driven automation systems.


Project stack

JavaScript
    │
    ├── Cloudflare Workers
    ├── Cron Triggers
    ├── Browserless
    ├── Puppeteer
    └── Claude.ai
Enter fullscreen mode Exit fullscreen mode

No traditional backend.

No database.

No always-on browser.

Just a scheduled serverless execution that spins up the resources it needs.


What's next?

The current implementation is intentionally small, but there are several things I'd like to improve:

  • Better retry and recovery logic
  • More robust account state detection
  • Execution logging
  • Better observability
  • Improved browser failure handling
  • More flexible account configuration
  • Cleaner deployment and setup
  • More extensive navigation testing

The next step isn't adding complexity for the sake of it.

It's making the automation more resilient when something inevitably changes.


Try it

If you want to look at the implementation:

GitHub: https://github.com/shlokkokk/claude-pinger

The repository is open source and the entire Worker is small enough to understand without digging through a massive codebase.

If you're building something similar with Cloudflare Workers and browser automation, I'm particularly interested in how you'd approach the reliability problem.

What would you change in the architecture?


Note: Use this with accounts you own and make sure your use of browser automation, account sessions, and the service itself complies with the applicable terms and policies.

Top comments (0)