Makuhari Development Corporation
5 min read, 943 words, last updated: 2025/11/25
TwitterLinkedInFacebookEmail

API Requests Blocked by Cloudflare: Debugging and Solutions

The Problem

You're building a web application and suddenly encounter a confusing error: your API calls are returning strange HTML content with messages like "Why have I been blocked? The action you just performed triggered the security solution." Instead of your expected JSON response, the frontend displays raw HTML source code across the page.

This creates two immediate issues:

  1. Your API functionality is completely broken
  2. Your users see ugly HTML markup instead of proper error messages

Let's dive into what's happening and how to fix it.

Investigation

Understanding the Root Cause

This issue typically manifests as a two-part problem:

  1. Backend Issue: Cloudflare's security services (WAF/Bot Fight/Rate Limiting) are intercepting and blocking your API requests
  2. Frontend Issue: Your application isn't properly handling non-JSON error responses

When Cloudflare blocks a request, it returns an HTML error page with Content-Type: text/html, but your frontend expects JSON. Without proper error handling, the raw HTML gets rendered directly to the page.

Common Cloudflare Blocking Triggers

Trigger Description
Bot Fight Mode API requests appear automated or lack proper browser headers
WAF Rules Request parameters contain suspicious patterns (SQL keywords, special characters)
Rate Limiting Too many requests in a short time period
IP Reputation Requests from flagged IP addresses
Missing Headers Lack of User-Agent, Origin, or Referer headers

Why APIs Go Through Cloudflare

Many developers assume Cloudflare only caches static assets, but when you enable the orange cloud (proxied) setting for your domain, all HTTP(S) traffic passes through Cloudflare, including:

  • API endpoints (/api/*)
  • File uploads
  • WebSocket connections
  • GraphQL queries

This happens regardless of caching behavior - Cloudflare acts as a reverse proxy for your entire domain.

Root Cause Analysis

The problem occurs because:

  1. Cloudflare intercepts the API request before it reaches your server
  2. Security rules trigger based on request patterns, headers, or content
  3. Cloudflare returns an HTML error page instead of forwarding to your API
  4. Your frontend assumes all API responses are JSON and tries to parse HTML as text
  5. Error handling fails and displays raw HTML to users

Solution

Fix 1: Improve Frontend Error Handling

The immediate fix is to add proper content-type checking in your API calls:

async function makeApiCall(url, options = {}) {
  try {
    const response = await fetch(url, options);
    const contentType = response.headers.get("content-type");
 
    // Check if response is actually JSON
    if (response.ok && contentType?.includes("application/json")) {
      return await response.json();
    }
 
    // Handle non-JSON responses (like Cloudflare blocks)
    const text = await response.text();
    
    if (!response.ok) {
      // Check if it's a Cloudflare block page
      if (text.includes("Cloudflare") || text.includes("blocked")) {
        throw new Error("Request blocked by security system. Please try again later.");
      }
      throw new Error(`Server error: ${response.status}`);
    }
 
    throw new Error(`Unexpected response format: ${contentType}`);
    
  } catch (error) {
    console.error("API call failed:", error);
    // Show user-friendly error instead of raw HTML
    throw new Error("Request failed. Please check your connection and try again.");
  }
}

Fix 2: Configure Cloudflare Security Rules

Navigate to your Cloudflare dashboard and adjust security settings:

Skip Security for API Routes

Security → WAF → Custom Rules:

Rule Expression: (http.request.uri.path contains "/api/")
Action: Skip - All remaining custom rules

Adjust Bot Fight Mode

Security → Bots:

  • Add your frontend domain to the allowlist
  • Consider switching from "Fight" to "Challenge" mode for API endpoints

Review Rate Limiting

Security → Rate Limiting:

  • Increase limits for authenticated API calls
  • Add bypass rules for legitimate traffic patterns

Fix 3: Use Dedicated API Subdomain

For better separation, consider using a separate subdomain for APIs:

www.example.com    → Frontend (Orange Cloud ✅)
api.example.com    → Backend APIs (Gray Cloud ⛅)

This completely bypasses Cloudflare for API traffic while maintaining protection for your frontend.

Fix 4: Implement Proper API Authentication

Add Cloudflare-compatible authentication:

// Add proper headers to API requests
const apiCall = fetch('/api/upload', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'User-Agent': 'YourApp/1.0',
    'X-Requested-With': 'XMLHttpRequest',
    // Add authentication token
    'Authorization': `Bearer ${token}`
  },
  body: JSON.stringify(data)
});

Prevention and Best Practices

1. Design Cloudflare-Friendly APIs

// Good: Structured error responses
app.use((err, req, res, next) => {
  res.status(err.status || 500).json({
    error: true,
    message: err.message,
    timestamp: new Date().toISOString()
  });
});
 
// Avoid: Plain text or HTML error responses

2. Monitor Cloudflare Security Events

Regularly check Security → Events to identify:

  • Which rules are triggering
  • Common false positive patterns
  • Traffic that should be allowlisted

3. Implement Graceful Degradation

// Fallback for blocked requests
const apiWithFallback = async (url, data) => {
  try {
    return await primaryApiCall(url, data);
  } catch (error) {
    if (error.message.includes('blocked')) {
      // Try alternative endpoint or show offline message
      return handleBlockedRequest();
    }
    throw error;
  }
};

4. Use Environment-Specific Configurations

const API_BASE = process.env.NODE_ENV === 'development' 
  ? 'http://localhost:3000/api'  // Direct connection
  : 'https://api.example.com';   // Through Cloudflare

Lessons Learned

  1. Always handle non-JSON responses in your API clients - external services can return HTML at any time
  2. Cloudflare proxies all traffic by default - not just static assets
  3. Security rules affect APIs differently than web pages - they're more likely to trigger on POST requests with large payloads
  4. Proper error handling improves user experience significantly during service disruptions
  5. Monitor security events proactively to prevent legitimate traffic from being blocked

By implementing these solutions, you'll create a more resilient application that gracefully handles Cloudflare security interventions while maintaining a good user experience.

Makuhari Development Corporation
法人番号: 6040001134259
サイトマップ
ご利用にあたって
個人情報保護方針
個人情報取扱に関する同意事項
お問い合わせ
Copyright© Makuhari Development Corporation. All Rights Reserved.