Author SHA1 Message Date
cloudflare-workers-and-pages[bot] 8d0e0497f7 Add Cloudflare Workers configuration 2026-07-02 04:05:05 +00:00
13 changed files with 2265 additions and 1725 deletions
-5
View File
@@ -27,8 +27,3 @@ SCRAPER_API_KEY=
# Deploy on Render.com free tier, Oracle Cloud, or any VPS
# Solves Cloudflare Turnstile challenges automatically
FLARESOLVERR_URL=
# Method 4: Scrape.do (1,000 free credits/month)
# Sign up at https://scrape.do/ (no credit card required)
# Handles Cloudflare, proxy rotation, CAPTCHA solving
SCRAPE_DO_TOKEN=
+6
View File
@@ -2,3 +2,9 @@ node_modules/
.env
.vercel/
deploy.cjs
# wrangler files
.wrangler
.dev.vars*
!.dev.vars.example
!.env.example
-42
View File
@@ -1,47 +1,5 @@
# Changelog
## v2.3.2
### Cloudflare Worker Implementation — Issue #2 Fix
#### New: `worker.js` (Cloudflare Worker Edge Runtime)
- **Full Cloudflare Worker implementation** created at project root
- Edge-to-edge requests bypass Cloudflare bot detection (Worker → miruro.to → Cloudflare trusts itself)
- Zero cold starts, 100K free requests/day on Cloudflare free tier
- No npm dependencies — uses native `fetch`, `DecompressionStream`, `TextEncoder`/`TextDecoder`
- 15 API endpoints: search, suggestions, filter, trending, trending/daily, trending/weekly, popular, top, upcoming, recent, random, info, episodes, watch, stream, genres, tags, providers, health
#### New: `wrangler.toml`
- Cloudflare Workers deployment configuration
- Compatible with `wrangler deploy` CLI
- Node.js compatibility flag enabled for buffer/text encoding support
- CPU time limit: 30 seconds
#### Architecture
```
Browser → Cloudflare Worker (edge) → miruro.to pipe → Cloudflare trusts itself ✅
Vercel (datacenter) → miruro.to → Cloudflare blocks ❌
```
#### Deploy
```bash
npm install -g wrangler
wrangler login
wrangler deploy worker.js --name miruroapi
```
#### Files Changed
- `worker.js` — Cloudflare Worker implementation (complete rewrite for edge runtime)
- `wrangler.toml` — Cloudflare Workers deployment configuration
- `CHANGELOG.md` — This entry
#### Notes
- This fixes Issue #2: Cloudflare Worker/Pages deployment support
- Streaming endpoints (`/episodes`, `/watch`, `/stream`) now work via edge-to-edge requests
- Environment variables `SCRAPER_API_KEY` and `FLARESOLVERR_URL` are optional for fallback methods
- The worker runs on Cloudflare's edge network with zero cold starts
---
## v2.3.1
### Cloudflare Worker Edition — Streaming Bypasses Cloudflare
-57
View File
@@ -50,37 +50,6 @@ MiruroAPI/
- Follow existing patterns in the codebase
- Keep helpers focused on one task
### File Headers
```js
/*
* ======= • ======= • ======= • ======= • =======• =======
* MiruroAPI — filename.js
* Repository: https://github.com/Shineii86/MiruroAPI
*
* @description
* What this module does.
*
* @author Shinei Nouzen
* @license MIT
* ======= • ======= • ======= • ======= • =======• =======
*/
```
### Section Markers
```js
// ══════════════════════════════════════════════════════════════
// SECTION NAME
// ══════════════════════════════════════════════════════════════
```
### Feature Markers
```js
// ---- FEATURE: Name ----
```
## Commit Messages
Use [Conventional Commits](https://www.conventionalcommits.org/):
@@ -106,32 +75,6 @@ Use [Conventional Commits](https://www.conventionalcommits.org/):
- Include expected vs actual behavior
- Include your Node.js version
## Contributing Bypass Solutions (Priority)
Streaming endpoints are blocked on cloud platforms. This is the most impactful contribution you can make.
### What to Build
Add a new fallback method in `src/helpers/pipe.js`. The file already has 3 methods (direct, ScraperAPI, FlareSolverr) — add yours as a 4th.
### Free/Open Source Options
| Tool | Language | Install |
|------|----------|---------|
| [nodriver](https://github.com/ultrafunkamsterdam/nodriver) | Python | `pip install nodriver` |
| [Camoufox](https://github.com/nicandris/camoufox) | Python | `pip install camoufox` |
| [curl_cffi](https://github.com/nicandris/curl_cffi) | Python | `pip install curl_cffi` |
| [patchright](https://github.com/nicandris/patchright) | Python | `pip install patchright` |
| [Scrape.do](https://scrape.do) | HTTP API | 1K free credits/mo |
### Steps
1. Fork and clone
2. Add your method in `src/helpers/pipe.js`
3. Add your API key/URL to `.env.example`
4. Test: `curl http://localhost:3000/api/episodes/20`
5. Submit PR
## License
By contributing, you agree that your contributions will be licensed under the MIT License.
+59 -92
View File
@@ -1,6 +1,3 @@
> [!NOTE]
> **API MAYBE Temporarily Paused** due to suspiciously too many requests. My hosted version of this API is only for testing purposes. You MUST host your own instance to use the API.
<div align="center">
<img src="https://capsule-render.vercel.app/api?type=waving&height=300&color=gradient&text=𝙈𝙞𝙧𝙪𝙧𝙤𝘼𝙋𝙄&fontAlignY=30&fontSize=100&desc=𝖠%20𝖢𝗈𝗆𝗉𝗅𝖾𝗍𝖾%20𝖱𝖤𝖲𝖳𝖿𝗎𝗅%20𝖠𝖯𝖨%20𝖥𝗈𝗋%20𝖠𝗇𝗂𝗆𝖾%20𝖲𝗍𝗋𝖾𝖺𝗆𝗂𝗇𝗀&descSize=25" />
@@ -22,7 +19,7 @@
<img src="https://img.shields.io/badge/AniList-GraphQL-02A6E4?style=flat-square&logo=graphql&logoColor=white" alt="AniList GraphQL"/>
<img src="https://img.shields.io/badge/Vercel-Serverless-000000?style=flat-square&logo=vercel&logoColor=white" alt="Vercel"/>
<img src="https://img.shields.io/badge/License-MIT-22c55e?style=flat-square&logo=mit&logoColor=white" alt="License"/>
<img src="https://img.shields.io/badge/Version-2.3.2-f43f8e?style=flat-square&logoColor=white" alt="Version"/>
<img src="https://img.shields.io/badge/Version-2.3.0-f43f8e?style=flat-square&logoColor=white" alt="Version"/>
<img src="https://img.shields.io/badge/Endpoints-46-6366f1?style=flat-square&logoColor=white" alt="Endpoints"/>
<img src="https://img.shields.io/badge/Providers-12-a855f7?style=flat-square&logoColor=white" alt="Providers"/>
</p>
@@ -101,7 +98,7 @@
- 🔒 **CORS Enabled** — Works from any frontend, no proxy needed
- 🚀 **Zero-Config Deploy** — One click to Vercel, or run standalone with Express
### 🔄 Self-Healing System (v2.3.2)
### 🔄 Self-Healing System (v2.3.0)
When Cloudflare blocks streaming requests, the API automatically tries fallback methods:
- **Direct** → Mirror rotation across 4 domains (miruro.to, miruro.ru, miruro.bz, miruro.tv)
@@ -112,28 +109,25 @@ Zero-config: works out of the box. Add `SCRAPER_API_KEY` env var for automatic C
### ⚠️ Streaming Status
> **Streaming endpoints work on Cloudflare Workers** — deploy `worker.js` for full streaming support.
> **Streaming endpoints (`/api/episodes`, `/api/watch`, `/api/sources`, `/api/stream`) return 500 errors when Cloudflare blocks pipe requests.**
>
> On Vercel, streaming endpoints (`/api/episodes`, `/api/watch`, `/api/sources`, `/api/stream`) return 500 errors when Cloudflare blocks pipe requests. Metadata endpoints (search, info, trending, etc.) work perfectly on all platforms.
> This is expected behavior on Vercel's free tier. Cloudflare's bot protection blocks requests from datacenter IPs (including Vercel's). Metadata endpoints (search, info, trending, etc.) work perfectly — only streaming is affected.
| What Works (All Platforms) | What's Blocked (Vercel Only) |
| What Works | What's Blocked |
|:---|:---|
| Search, suggestions, filter | Episodes, sources, stream |
| Info, characters, relations | Watch, download |
| Trending, popular, schedule | All pipe-dependent endpoints |
| Genres, tags, calendar | Streaming provider data |
| All AniList-backed endpoints | **✅ Works on Cloudflare Worker** |
| All AniList-backed endpoints | |
**To fix streaming on Vercel**, set one of these environment variables:
**To fix streaming**, set one of these environment variables in Vercel:
```bash
# Option 1: Deploy as Cloudflare Worker (recommended — free, bypasses Cloudflare)
wrangler deploy worker.js --name miruroapi
# Option 2: ScraperAPI (requires premium plan — $49/month)
# Option 1: ScraperAPI (requires premium plan — $49/month)
SCRAPER_API_KEY=your_scraperapi_key
# Option 3: FlareSolverr (self-hosted, unlimited)
# Option 2: FlareSolverr (self-hosted, unlimited)
FLARESOLVERR_URL=http://your-flaresolverr-host:8191
```
@@ -539,7 +533,7 @@ console.log(resp.data);
"success": true,
"results": {
"status": "healthy",
"version": "2.3.2",
"version": "2.3.0",
"uptime": "0h 0m 34s",
"uptimeSeconds": 34,
"timestamp": "2026-06-09T09:55:00.884Z",
@@ -1420,9 +1414,9 @@ docker build -t miruroapi .
docker run -p 3000:3000 miruroapi
```
### ⚡ Cloudflare Worker (Streaming Fixed)
### ⚡ Cloudflare Worker (Streaming Works!)
> **Streaming endpoints work on Cloudflare Workers** — edge-to-edge requests bypass Cloudflare bot detection.
> **Streaming endpoints work on Workers** — requests to Miruro bypass Cloudflare bot detection because Workers run on Cloudflare's edge network (edge-to-edge traffic is trusted).
```bash
# Install wrangler CLI
@@ -1431,23 +1425,20 @@ npm install -g wrangler
# Login to Cloudflare
wrangler login
# Deploy worker
# Deploy
wrangler deploy worker.js --name miruroapi
```
**Why Workers Work:**
```
Vercel (datacenter) → miruro.to → Cloudflare blocks ❌
Worker (edge) → miruro.to → Cloudflare trusts itself ✅
```
Your API is live at: `https://miruroapi.YOUR_SUBDOMAIN.workers.dev`
**Features:** Zero cold starts, 100K free requests/day, no npm dependencies, 15 API endpoints.
| Feature | Vercel | Cloudflare Worker |
|---------|--------|-------------------|
| Streaming (pipe) | Blocked (403) | Works |
| Cold starts | ~500ms | Zero |
| Free tier | Unlimited | 100K req/day |
| npm deps | Yes | No (native fetch) |
**Optional env vars:**
```bash
wrangler secret put SCRAPER_API_KEY # ScraperAPI premium key ($49/mo)
wrangler secret put FLARESOLVERR_URL # FlareSolverr Docker URL
```
> See `worker.js` for the full Worker implementation with 15 endpoints.
---
@@ -1486,8 +1477,7 @@ wrangler secret put FLARESOLVERR_URL # FlareSolverr Docker URL
| Version | Date | Key Changes |
|:---|:---|:---|
| **2.3.2** | 2026-08-05 | Cloudflare Worker implementation — edge-to-edge streaming bypass, wrangler.toml, 15 Worker endpoints |
| **2.3.1** | 2026-07-02 | Self-healing fallback system — multi-method pipe recovery, /api/pipe-health endpoint, ScraperAPI + FlareSolverr support |
| **2.3.0** | 2026-07-02 | Self-healing fallback system — multi-method pipe recovery, /api/pipe-health endpoint, ScraperAPI + FlareSolverr support |
| **2.1.4** | 2026-06-25 | Security hardening — XOR keys to env vars, CORS restriction, input sanitization, bug fixes (multi-search, deepTranslate, getBestStream) |
| **2.1.3** | 2026-06-25 | Diagnostic sweep — tags, random, character/staff 404 fixes, pipe retry with backoff, security headers |
| **2.1.2** | 2026-06-25 | Streaming architecture — pru proxy decode, CDN CORS proxy, raw stream URLs |
@@ -1528,9 +1518,42 @@ Cloudflare detects:
- Missing browser fingerprint headers
- Non-residential traffic patterns
#### Fix 1: FlareSolverr (Best — Free, Works!)
#### Fix 1: Cloudflare Worker (Best — Free, Works!)
FlareSolverr runs a headless browser that bypasses Cloudflare automatically. This is the most reliable fix.
Workers run on Cloudflare's edge network. Edge-to-edge requests are trusted — no bot detection.
```bash
# 1. Install wrangler
npm install -g wrangler
# 2. Login
wrangler login
# 3. Deploy
wrangler deploy worker.js --name miruroapi
# 4. Your streaming now works at:
# https://miruroapi.YOUR_SUBDOMAIN.workers.dev/api/episodes/20
```
**Cost:** Free (100K requests/day). No API key needed.
#### Fix 2: ScraperAPI (Paid — $49/month)
ScraperAPI proxies your requests through residential IPs, bypassing Cloudflare.
```bash
# 1. Sign up at https://www.scraperapi.com/ (free 1,000 requests/month)
# 2. Get your API key from the dashboard
# 3. Add to Vercel environment variables:
SCRAPER_API_KEY=your_api_key_here
```
**Cost:** $49/month (premium plan required for protected domains like Miruro).
#### Fix 3: FlareSolverr (Self-Hosted — Unlimited)
FlareSolverr runs a headless browser that bypasses Cloudflare automatically.
```bash
# 1. Run FlareSolverr on your own server
@@ -1547,22 +1570,9 @@ FLARESOLVERR_URL=http://your-server-ip:8191
- Public IP address
- Docker installed
#### Fix 2: ScraperAPI (Paid — $49/month)
#### Fix 4: Self-Host the Entire API
ScraperAPI proxies your requests through residential IPs, bypassing Cloudflare.
```bash
# 1. Sign up at https://www.scraperapi.com/
# 2. Get your API key from the dashboard
# 3. Add to Vercel environment variables:
SCRAPER_API_KEY=your_api_key_here
```
**Cost:** $49/month (premium plan required for protected domains like Miruro).
#### Fix 3: Self-Host the Entire API
If you run the API on your own VPS (not Vercel), requests come from your IP which may not be blocked.
If you run the API on your own VPS (not Vercel), requests come from your residential/datacenter IP which may not be blocked.
```bash
# Clone and install
@@ -1601,49 +1611,6 @@ Expected response when streaming works:
}
```
### 🤝 Contributing Bypass Solutions
Streaming is blocked on all cloud platforms. We need help! If you can implement any of these, PRs are welcome:
#### Free / Open Source (Best for self-hosted)
| Tool | Language | How It Works | Notes |
|------|----------|-------------|-------|
| [nodriver](https://github.com/ultrafunkamsterdam/nodriver) | Python | CDP-based browser automation, bypasses automation detection | Successor to undetected-chromedriver |
| [Camoufox](https://github.com/nicandris/camoufox) | Python | Stealth Firefox with fingerprint spoofing | 82% baseline Turnstile bypass |
| [curl_cffi](https://github.com/nicandris/curl_cffi) | Python | TLS fingerprint impersonation | Lightweight, no browser needed |
| [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) | Docker | Headless Chrome proxy server | Can't solve interactive CAPTCHAs |
| [patchright](https://github.com/nicandris/patchright) | Python | Patched Playwright fork | Drop-in Playwright replacement |
| [scrapy-impersonate](https://github.com/driver-utils/scrapy-impersonate) | Python | Scrapy with TLS impersonation | For Scrapy users |
#### Paid APIs (Good for cloud deployments)
| Service | Free Tier | Price | API Example |
|---------|-----------|-------|-------------|
| [Scrape.do](https://scrape.do) | 1,000 credits/mo | $0.08/1K | `https://api.scrape.do/?url=...&token=...` |
| [ZenRows](https://zenrows.com) | Trial | $49/mo | `https://api.zenrows.com/?url=...&apikey=...` |
| [ScrapingBee](https://scrapingbee.com) | Trial | $49/mo | `https://app.scrapingbee.com/api/v1/?...` |
#### What to Implement
1. **Node.js integration** — Add `nodriver` or `Camoufox` as a pipe fallback in `src/helpers/pipe.js`
2. **Scrape.do adapter** — Simple HTTP proxy, 1K free credits/mo, no browser needed
3. **Playwright stealth mode** — Use `patchright` or `playwright-extra-stealth` for browser-based bypass
4. **Residential proxy support** — Add proxy rotation for pipe requests
#### How to Contribute
1. Fork the repo
2. Add your bypass method as a new fallback in `src/helpers/pipe.js`
3. Add your API key to `.env.example`
4. Test with: `curl http://localhost:3000/api/episodes/20`
5. Submit a PR
```bash
# Example: Add Scrape.do as a fallback
SCRAPE_DO_TOKEN=your_token_here
```
### 🐛 Debug Mode
```bash
+48
View File
@@ -5,6 +5,7 @@
```
MiruroAPI/
├── server.js # Express entry point, port 3000
├── worker.js # Cloudflare Worker edition (edge runtime)
├── package.json # name: "miruro-api"
├── vercel.json # Routes /api/* and /* to server.js
├── Dockerfile # Docker support (node:20-alpine)
@@ -199,4 +200,51 @@ Error responses:
| cors | ^2.8.5 | CORS headers |
| dotenv | ^16.4.0 | Environment variables |
## Cloudflare Worker Architecture (v2.3.1)
The Worker edition (`worker.js`) runs the same API on Cloudflare's edge network. Key difference: **streaming endpoints work** because edge-to-edge requests bypass Cloudflare bot detection.
### Why Workers Work
```
Vercel (datacenter IP) → miruro.to → Cloudflare WAF → 403 Blocked
Cloudflare Worker (edge) → miruro.to → Cloudflare internal network → 200 OK
```
### Worker Runtime Differences
| Feature | Express (Node.js) | Cloudflare Worker |
|---------|-------------------|-------------------|
| HTTP client | axios | native fetch |
| Decompression | zlib (Node.js) | DecompressionStream (Web API) |
| Caching | in-memory Map | Workers KV (optional) |
| npm packages | Yes | No (bundle only) |
| Cold starts | ~500ms | Zero |
| CPU limit | None | 10ms (free) / 30s (paid) |
### Worker Endpoints (15)
| Endpoint | Description |
|----------|-------------|
| `GET /api/health` | System health check |
| `GET /api/search?query=` | Full-text anime search |
| `GET /api/suggestions?query=` | Autocomplete suggestions |
| `GET /api/filter?genre=` | Advanced filter |
| `GET /api/trending` | Trending anime |
| `GET /api/popular` | Most popular |
| `GET /api/top` | Top scored |
| `GET /api/random` | Random anime |
| `GET /api/info/:id` | Full anime info |
| `GET /api/anime/:id/characters` | Characters + voice actors |
| `GET /api/anime/:id/relations` | Related anime |
| `GET /api/genres` | All genres |
| `GET /api/episodes/:id` | Episode list (pipe) |
| `GET /api/watch/:provider/:anilistId/:category/:slug` | Streaming sources (pipe) |
### Deploy
```bash
npm install -g wrangler
wrangler login
wrangler deploy worker.js --name miruroapi
```
+1466 -3
View File
File diff suppressed because it is too large Load Diff
+6 -3
View File
@@ -1,12 +1,14 @@
{
"name": "miruro-api",
"version": "2.3.2",
"version": "2.3.0",
"description": "RESTful API for Miruro - Anime streaming data powered by AniList GraphQL and Miruro streaming providers",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"test": "node test.js"
"test": "node test.js",
"deploy": "wrangler deploy",
"preview": "wrangler dev"
},
"dependencies": {
"axios": "^1.8.0",
@@ -16,7 +18,8 @@
"express": "^4.21.0"
},
"devDependencies": {
"nodemon": "^3.1.0"
"nodemon": "^3.1.0",
"wrangler": "^4.106.0"
},
"keywords": [
"anime",
+1 -1
View File
@@ -301,7 +301,7 @@ app.use((req, res) => {
if (!process.env.VERCEL) {
app.listen(PORT, () => {
console.log(`[${new Date().toISOString()}] MiruroAPI v2.3.2 listening at ${PORT}`);
console.log(`[${new Date().toISOString()}] MiruroAPI v2.3.0 listening at ${PORT}`);
});
}
+2 -2
View File
@@ -1124,7 +1124,7 @@ const createApiRoutes = (jsonResponse, jsonError, startTime) => {
success: true,
results: {
status: "healthy",
version: "2.3.2",
version: "2.3.0",
uptime: `${hours}h ${minutes}m ${seconds}s`,
uptimeSeconds: uptime,
timestamp: new Date().toISOString(),
@@ -1211,7 +1211,7 @@ const createApiRoutes = (jsonResponse, jsonError, startTime) => {
info: {
title: "MiruroAPI",
description: "Free REST API for anime streaming data — AniList GraphQL + Miruro streaming providers",
version: "2.3.2",
version: "2.3.0",
contact: { name: "Shineii86", url: "https://github.com/Shineii86/MiruroAPI" },
},
servers: [
+663 -1498
View File
File diff suppressed because it is too large Load Diff
+14
View File
@@ -0,0 +1,14 @@
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "miruroapi",
"compatibility_date": "2026-07-02",
"observability": {
"enabled": true
},
"assets": {
"directory": "public"
},
"compatibility_flags": [
"nodejs_compat"
]
}
-22
View File
@@ -1,22 +0,0 @@
name = "miruroapi"
main = "worker.js"
compatibility_date = "2024-01-01"
# Cloudflare Worker configuration for MiruroAPI
# Deploy with: wrangler deploy
# Environment variables (set via wrangler secret put or dashboard)
# SCRAPER_API_KEY = "" # ScraperAPI premium key (optional, $49/mo)
# FLARESOLVERR_URL = "" # FlareSolverr Docker instance URL (optional)
# Route configuration (optional — for custom domains)
# routes = [
# { pattern = "api.your-domain.com/api/*", zone_name = "your-domain.com" }
# ]
# Limits
[limits]
cpu_ms = 30000
# Compatibility flags
compatibility_flags = ["nodejs_compat"]