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." │
└────────────┬─────────────┘
│
▼
"."
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
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.
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.
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
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.
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
...
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.
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
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
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 * * *"]
}
}
The execution lifecycle becomes:
asleep
│
▼
cron fires
│
▼
Worker starts
│
▼
Browser automation
│
▼
Claude ping
│
▼
Worker finishes
│
▼
asleep
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
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.
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
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
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
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.
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
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)