{"slug": "how-i-automated-claudes-5-hour-usage-window-with-cloudflare-workers-puppeteer", "title": "How I Automated Claude’s 5-Hour Usage Window with Cloudflare Workers & Puppeteer", "summary": "Developer Shlok Kokkonda built Claude Pinger, a serverless service using Cloudflare Workers, Browserless, and Puppeteer to automate sending a minimal ping to Claude.ai every five hours, keeping the AI's rolling usage window active without manual intervention. The service supports multiple accounts and is available on GitHub.", "body_md": "I got tired of manually sending a message to Claude just to start its 5-hour rolling usage window.\n\nSo I automated it.\n\nNot with a VPS.\n\nNot with a browser running 24/7.\n\nWith a **Cloudflare Worker, Browserless, and Puppeteer**.\n\nThe 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.\n\n**GitHub:** [https://github.com/shlokkokk/claude-pinger](https://github.com/shlokkokk/claude-pinger)\n\nClaude uses a rolling 5-hour usage window.\n\nThe part that bothered me was that the window doesn't start counting down until the account actually sends a message.\n\nIf you're not actively using Claude, nothing happens.\n\nSo if I wanted the window to be active before I started working, I had to remember to manually open Claude and send something.\n\nThat's exactly the kind of repetitive task I prefer to automate.\n\nThe requirements were straightforward:\n\nThat led to this architecture.\n\n```\n┌──────────────────────────┐\n│      Cloudflare Cron     │\n│        Every 5 hours     │\n└────────────┬─────────────┘\n             │\n             ▼\n┌──────────────────────────┐\n│     Cloudflare Worker    │\n│       Orchestration      │\n└────────────┬─────────────┘\n             │\n             ▼\n┌──────────────────────────┐\n│        Browserless       │\n│    Remote Browser API    │\n└────────────┬─────────────┘\n             │\n             ▼\n┌──────────────────────────┐\n│        Puppeteer         │\n│     Browser Automation   │\n└────────────┬─────────────┘\n             │\n             ▼\n┌──────────────────────────┐\n│         Claude.ai        │\n│                          │\n│  \"ping. Reply with '.'   │\n│           only.\"         │\n└────────────┬─────────────┘\n             │\n             ▼\n            \".\"\n```\n\nEach component has one job:\n\n| Component | Responsibility |\n|---|---|\nCloudflare Cron |\nDecides when the automation runs |\nCloudflare Worker |\nOrchestrates the execution |\nBrowserless |\nProvides the remote browser |\nPuppeteer |\nControls the browser |\nClaude.ai |\nReceives the ping |\nWorker Secrets |\nStores credentials |\n\nThe Worker wakes up, performs the automation, and finishes.\n\nThere is no reason to keep a browser process alive between executions.\n\nCloudflare Workers aren't designed to run a full browser themselves.\n\nI still wanted the Worker to be responsible for scheduling and orchestration, though.\n\nSo the Worker calls **Browserless**, which provides the remote browser environment.\n\nThat gives the project a clean separation:\n\n```\nCloudflare\n    │\n    │ schedule + orchestration\n    ▼\nBrowserless\n    │\n    │ browser execution\n    ▼\nPuppeteer\n    │\n    │ interaction\n    ▼\nClaude.ai\n```\n\nThe Worker doesn't need to maintain a browser server.\n\nIt simply requests a browser session when the job runs.\n\nThe automation doesn't need Claude to generate anything meaningful.\n\nIt only needs to send a message.\n\nSo the prompt is intentionally tiny:\n\n```\nping. Reply with '.' only.\n```\n\nThe expected response:\n\n```\n.\n```\n\nThe idea is simple:\n\n**start the interaction while keeping the generated response as small as possible.**\n\nThis isn't prompt engineering for better answers.\n\nIt's prompt engineering for a smaller answer.\n\nI didn't want to deploy one Worker per Claude account.\n\nClaude Pinger can process multiple configured accounts during the same execution.\n\nConceptually:\n\n```\n                    Cloudflare Worker\n                           │\n             ┌─────────────┼─────────────┐\n             │             │             │\n             ▼             ▼             ▼\n         Account 1      Account 2      Account 3\n             │             │             │\n             ▼             ▼             ▼\n        Browserless    Browserless    Browserless\n             │             │             │\n             ▼             ▼             ▼\n          Claude         Claude         Claude\n```\n\nAdditional accounts are configured through Worker Secrets:\n\n```\nwrangler secret put CLAUDE_SESSION_KEY_2\nwrangler secret put CLAUDE_SESSION_KEY_3\n```\n\nThe same Worker can then process the configured accounts during its scheduled execution.\n\nAnother problem was conversation clutter.\n\nIf the automation created a new conversation every five hours, the sidebar would eventually become:\n\n```\nPing test\nPing test\nPing test\nPing test\nPing test\nPing test\n...\n```\n\nInstead, Claude Pinger can reuse a dedicated conversation.\n\nFor example:\n\n```\nPing test\n```\n\nA direct conversation URL can be configured with:\n\n```\nwrangler secret put CLAUDE_CHAT_URL_1\n```\n\nThat gives the automation a stable target instead of creating a new conversation every time.\n\nThis is where browser automation gets interesting.\n\nA script that works once isn't necessarily a reliable automation system.\n\nClaude Pinger supports two navigation paths.\n\nIf a chat URL is configured:\n\n```\nCLAUDE_CHAT_URL_1\n```\n\nthe automation attempts to open it directly.\n\nIf direct navigation isn't available or fails, the automation can fall back to the recent chats interface and locate the configured conversation.\n\nThe logic is essentially:\n\n```\n             Start\n               │\n               ▼\n       Chat URL available?\n          /           \\\n        yes            no\n         │              │\n         ▼              ▼\n    Open chat       Open recents\n         │              │\n         │              ▼\n         │         Find conversation\n         │              │\n         └──────┬───────┘\n                ▼\n            Send ping\n```\n\nThis matters because unattended browser automation has to assume that things will occasionally fail.\n\nThe Worker is scheduled using a Cloudflare Cron Trigger.\n\nThe configuration is:\n\n```\n{\n  \"name\": \"claude-pinger\",\n  \"main\": \"src/index.js\",\n  \"compatibility_date\": \"2024-01-01\",\n  \"triggers\": {\n    \"crons\": [\"0 */5 * * *\"]\n  }\n}\n```\n\nThe execution lifecycle becomes:\n\n```\n        asleep\n           │\n           ▼\n      cron fires\n           │\n           ▼\n     Worker starts\n           │\n           ▼\n   Browser automation\n           │\n           ▼\n       Claude ping\n           │\n           ▼\n     Worker finishes\n           │\n           ▼\n        asleep\n```\n\nThat's the entire server-side lifecycle.\n\nTyping a message into a browser is easy.\n\nMaking that process run unattended is the actual engineering problem.\n\nYou have to account for:\n\nA browser script that works perfectly while you're watching it is very different from one that needs to run by itself for weeks.\n\nThat's where most of the interesting work ended up.\n\nClaude session keys are authenticated credentials.\n\nThey should never be hardcoded into the repository.\n\nClaude Pinger uses Cloudflare Worker Secrets:\n\n```\nwrangler secret put BROWSERLESS_TOKEN\n\nwrangler secret put CLAUDE_SESSION_KEY\n\nwrangler secret put CLAUDE_SESSION_KEY_2\n```\n\nChat URLs can also be stored as secrets:\n\n```\nwrangler secret put CLAUDE_CHAT_URL_1\n```\n\nThis keeps credentials outside the source code.\n\nSecurity 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.\n\nYou'll need:\n\nInstall Wrangler:\n\n```\nnpm install -g wrangler\n```\n\nClone the repository:\n\n```\ngit clone https://github.com/shlokkokk/claude-pinger.git\ncd claude-pinger\n```\n\nConfigure Browserless:\n\n```\nwrangler secret put BROWSERLESS_TOKEN\n```\n\nConfigure your primary Claude account:\n\n```\nwrangler secret put CLAUDE_SESSION_KEY\n```\n\nOptional second account:\n\n```\nwrangler secret put CLAUDE_SESSION_KEY_2\n```\n\nOptional direct chat URL:\n\n```\nwrangler secret put CLAUDE_CHAT_URL_1\n```\n\nThen deploy:\n\n```\nwrangler deploy\n```\n\nThe cron trigger isn't the only way to run it.\n\nYou can manually execute the Worker:\n\n```\ncurl -X POST https://<your-worker-subdomain>.workers.dev\n```\n\nA successful execution returns information about the accounts processed:\n\n```\n{\n  \"message\": \"Multi-account ping finished!\",\n  \"results\": [\n    {\n      \"account\": \"Account 1\",\n      \"result\": {\n        \"success\": true,\n        \"url\": \"https://claude.ai/chat/...\",\n        \"pageTitle\": \"Ping test - Claude\",\n        \"actionExecuted\": true,\n        \"stepError\": null\n      }\n    }\n  ]\n}\n```\n\nThat makes it much easier to test the automation before relying on the scheduled execution.\n\nCloudflare Workers are usually associated with APIs, middleware, edge functions, and lightweight web services.\n\nThis project uses them slightly differently.\n\nThe Worker is essentially acting as an **automation orchestrator**.\n\nIt doesn't run the browser itself.\n\nIt doesn't store application state.\n\nIt doesn't need a database.\n\nIt doesn't need a server running continuously.\n\nIt simply coordinates:\n\n**schedule → browser session → authentication → navigation → action → result**\n\nand then disappears.\n\nThat's a pretty useful pattern for small, event-driven automation systems.\n\n```\nJavaScript\n    │\n    ├── Cloudflare Workers\n    ├── Cron Triggers\n    ├── Browserless\n    ├── Puppeteer\n    └── Claude.ai\n```\n\nNo traditional backend.\n\nNo database.\n\nNo always-on browser.\n\nJust a scheduled serverless execution that spins up the resources it needs.\n\nThe current implementation is intentionally small, but there are several things I'd like to improve:\n\nThe next step isn't adding complexity for the sake of it.\n\nIt's making the automation more resilient when something inevitably changes.\n\nIf you want to look at the implementation:\n\n**GitHub:** [https://github.com/shlokkokk/claude-pinger](https://github.com/shlokkokk/claude-pinger)\n\nThe repository is open source and the entire Worker is small enough to understand without digging through a massive codebase.\n\nIf you're building something similar with Cloudflare Workers and browser automation, I'm particularly interested in how you'd approach the reliability problem.\n\n**What would you change in the architecture?**\n\nNote: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.", "url": "https://wpnews.pro/news/how-i-automated-claudes-5-hour-usage-window-with-cloudflare-workers-puppeteer", "canonical_source": "https://dev.to/shlokkokk/how-i-automated-claudes-5-hour-usage-window-with-cloudflare-workers-puppeteer-550m", "published_at": "2026-08-17 14:52:28+00:00", "updated_at": "2026-08-17 15:13:56.219994+00:00", "lang": "en", "topics": ["developer-tools", "ai-products"], "entities": ["Shlok Kokkonda", "Claude Pinger", "Cloudflare Workers", "Browserless", "Puppeteer", "Claude.ai", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/how-i-automated-claudes-5-hour-usage-window-with-cloudflare-workers-puppeteer", "markdown": "https://wpnews.pro/news/how-i-automated-claudes-5-hour-usage-window-with-cloudflare-workers-puppeteer.md", "text": "https://wpnews.pro/news/how-i-automated-claudes-5-hour-usage-window-with-cloudflare-workers-puppeteer.txt", "jsonld": "https://wpnews.pro/news/how-i-automated-claudes-5-hour-usage-window-with-cloudflare-workers-puppeteer.jsonld"}}