CloudFlare Bypass

A Flutter package for bypassing CloudFlare protection using Dio HTTP client and WebView. This package provides automatic CloudFlare detection, cookie management, and a WebView-based challenge solver.

Features

  • CloudFlare Detection: Automatically detects CloudFlare protection (captcha/challenge and blocked states)
  • WebView Bypass: Full-screen WebView for solving CloudFlare challenges
  • Cookie Management: Persistent cookie storage with WebView synchronization
  • Dio Interceptors: Integrates seamlessly with Dio HTTP client
  • Rate Limiting: Built-in rate limit handling with exponential backoff
  • Browser Headers: Automatic browser-like headers to avoid detection

Installation

Add this to your pubspec.yaml:

dependencies:
  cloudflare_bypass: any

For local development:

dependencies:
  cloudflare_bypass:
    path: ../cloudflare_bypass

Quick Start

Basic Usage

import 'package:cloudflare_bypass/cloudflare_bypass.dart';

// Create the client
final client = await BypassHttpClient.create(
  config: ClientConfig(
    baseUrl: 'https://example.com',
  ),
);

// Make requests - CloudFlare bypass is automatic!
try {
  final response = await client.get('/api/data');
  print(response.data);
} on CloudFlareDioError catch (e) {
  // Handle CloudFlare errors
  print('CloudFlare protection: ${e.cloudFlareException.message}');
}

With Context (for automatic bypass UI)

class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> with BypassHttpClientMixin {
  late BypassHttpClient _client;

  @override
  void initState() {
    super.initState();
    _initClient();
  }

  Future<void> _initClient() async {
    _client = await BypassHttpClient.create();
    initHttpClient(_client); // This provides context for bypass UI
  }

  Future<void> _makeRequest() async {
    // When CloudFlare is detected, bypass page shows automatically
    final response = await _client.get('https://protected-site.com');
  }
}

Manual Bypass

final result = await CloudFlareWebView.show(
  context,
  url: 'https://protected-site.com',
  cookieJar: client.cookieJar,
);

if (result.success) {
  // Cookies are now stored, retry your request
  final response = await client.get('https://protected-site.com');
}

Configuration

final config = ClientConfig(
  // Base URL for all requests
  baseUrl: 'https://example.com',

  // Custom user agent
  userAgent: ClientConfig.chromeDesktopUserAgent,

  // Timeouts
  connectTimeout: Duration(seconds: 20),
  receiveTimeout: Duration(seconds: 60),

  // Rate limiting
  enableRateLimiting: true,
  rateLimitMaxRetries: 3,

  // CloudFlare bypass settings
  cloudFlareBypassTimeout: Duration(minutes: 2),
  useInterceptClient: true, // Filter problematic headers

  // Logging
  enableLogging: true,

  // Source identifier for tracking
  source: 'my-app',
);

final client = await BypassHttpClient.create(config: config);

Components

CloudFlareHelper

Utility class for CloudFlare detection:

// Check response for protection
final state = CloudFlareHelper.checkResponseForProtection(response);
if (state == CloudFlareHelper.protectionCaptcha) {
  // Captcha required
}

// Check if a cookie is from CloudFlare
if (CloudFlareHelper.isCloudFlareCookie('cf_clearance')) {
  // It's a CloudFlare cookie
}

// Get clearance cookie value
final clearance = CloudFlareHelper.getClearanceFromCookieString(cookieHeader);

Exceptions

try {
  await client.get('/protected');
} on CloudFlareDioError catch (e) {
  final cfException = e.cloudFlareException;

  if (cfException is CloudFlareProtectedException) {
    // Captcha required
    print('URL: ${cfException.url}');
    print('Headers: ${cfException.headers}');
  } else if (cfException is CloudFlareBlockedException) {
    // IP is blocked
    print('Your IP is blocked');
  }
}
// Get cookies for a URL
final cookies = await client.getCookies(Uri.parse('https://example.com'));

// Clear all cookies
await client.clearCookies();

// Clear cookies for specific URL
await client.clearCookiesForUrl(Uri.parse('https://example.com'));
// Create persistent cookie jar
final cookieJar = await PersistentCookieJar.create();

// Use with client
final client = await BypassHttpClient.create(
  cookieJar: cookieJar,
);

// Or use standalone
await cookieJar.saveFromResponse(uri, cookies);
final loadedCookies = await cookieJar.loadForRequest(uri);

WebView Request Interception

Capture AJAX requests for tokens:

final interceptor = WebViewRequestInterceptor(cookieJar: cookieJar);

// Capture URLs matching a pattern
final urls = await interceptor.captureUrls(
  'https://example.com/page',
  urlPattern: RegExp(r'/api/token'),
  timeout: Duration(seconds: 15),
);

// Capture first matching URL
final tokenUrl = await interceptor.captureFirstUrl(
  'https://example.com/page',
  urlPattern: RegExp(r'vrf=\w+'),
);

WebView Executor

Execute JavaScript in a page:

final executor = WebViewExecutor(cookieJar: cookieJar);

// Execute custom JavaScript
final result = await executor.execute(
  'https://example.com',
  'document.querySelector("meta[name=token]").content',
);

if (result.success) {
  print('Token: ${result.result}');
}

// Extract by selector
final title = await executor.extractBySelector(
  'https://example.com',
  'h1.title',
  attribute: 'textContent',
);

Interceptors

CloudFlareInterceptor

Automatically detects CloudFlare and can trigger bypass:

dio.interceptors.add(CloudFlareInterceptor(
  source: 'my-source',
  onCloudFlareChallenge: (url, headers) async {
    // Show bypass UI and return success/failure
    return await showBypassPage(url);
  },
  autoRetry: true,
  maxRetries: 1,
));

CommonHeadersInterceptor

Adds browser-like headers:

dio.interceptors.add(CommonHeadersInterceptor(
  userAgent: 'Mozilla/5.0 ...',
  addAcceptHeaders: true,
  addAcceptLanguage: true,
  blockedHeaders: BlockedHeaders.forCloudFlareBypass,
));

RateLimitInterceptor

Handles HTTP 429 responses:

dio.interceptors.add(RateLimitInterceptor(
  maxRetries: 3,
  baseDelayMs: 1000,
  maxDelayMs: 30000,
));

Architecture

This package is inspired by the Kotatsu-Redo Android app's network architecture:

Request Flow:
┌─────────────────────────────────────────────────────────────┐
│  BypassHttpClient                                           │
│  ├── CommonHeadersInterceptor (add browser headers)         │
│  ├── CookieManager (manage cookies)                         │
│  ├── RateLimitInterceptor (handle 429)                      │
│  └── CloudFlareInterceptor (detect & bypass CF)             │
│       ↓                                                     │
│  CloudFlare Detected → CloudFlareWebView (solve challenge)  │
│       ↓                                                     │
│  Cookies Saved → Retry Request                              │
└─────────────────────────────────────────────────────────────┘

Platform Support

Platform Support
Android
iOS
Web ❌ (WebView not available)
Windows ❌ (WebView limited)
macOS ❌ (WebView limited)
Linux ❌ (WebView limited)

Example

See the example directory for a complete demo app.

License

MIT License - see LICENSE file for details.

Credits

Inspired by Kotatsu Android app's CloudFlare bypass implementation.

Libraries

cloudflare_bypass
A Flutter package for bypassing CloudFlare protection using Dio HTTP client and WebView with automatic cookie management and captcha resolution.