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

> Source: <https://dev.to/shlokkokk/how-i-automated-claudes-5-hour-usage-window-with-cloudflare-workers-puppeteer-550m>
> Published: 2026-08-17 14:52:28+00:00

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](https://github.com/shlokkokk/claude-pinger)

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:

That led to this architecture.

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

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.

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
```

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

It simply requests a browser session when the job runs.

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.
```

The expected response:

```
.
```

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.

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
```

Additional accounts are configured through Worker Secrets:

```
wrangler secret put CLAUDE_SESSION_KEY_2
wrangler secret put CLAUDE_SESSION_KEY_3
```

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

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
...
```

Instead, Claude Pinger can reuse a dedicated conversation.

For example:

```
Ping test
```

A direct conversation URL can be configured with:

```
wrangler secret put CLAUDE_CHAT_URL_1
```

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

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.

If a chat URL is configured:

```
CLAUDE_CHAT_URL_1
```

the automation attempts to open it directly.

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
```

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

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 * * *"]
  }
}
```

The execution lifecycle becomes:

```
        asleep
           │
           ▼
      cron fires
           │
           ▼
     Worker starts
           │
           ▼
   Browser automation
           │
           ▼
       Claude ping
           │
           ▼
     Worker finishes
           │
           ▼
        asleep
```

That's the entire server-side lifecycle.

Typing a message into a browser is easy.

Making that process run unattended is the actual engineering problem.

You have to account for:

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.

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
```

Chat URLs can also be stored as secrets:

```
wrangler secret put CLAUDE_CHAT_URL_1
```

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.

You'll need:

Install Wrangler:

```
npm install -g wrangler
```

Clone the repository:

```
git clone https://github.com/shlokkokk/claude-pinger.git
cd claude-pinger
```

Configure Browserless:

```
wrangler secret put BROWSERLESS_TOKEN
```

Configure your primary Claude account:

```
wrangler secret put CLAUDE_SESSION_KEY
```

Optional second account:

```
wrangler secret put CLAUDE_SESSION_KEY_2
```

Optional direct chat URL:

```
wrangler secret put CLAUDE_CHAT_URL_1
```

Then deploy:

```
wrangler deploy
```

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
```

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
      }
    }
  ]
}
```

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

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.

```
JavaScript
    │
    ├── Cloudflare Workers
    ├── Cron Triggers
    ├── Browserless
    ├── Puppeteer
    └── Claude.ai
```

No traditional backend.

No database.

No always-on browser.

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

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

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

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

If you want to look at the implementation:

**GitHub:** [https://github.com/shlokkokk/claude-pinger](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.
