cd /news/ai-tools/building-a-resilient-ai-text-humaniz… · home › topics › ai-tools › article
[ARTICLE · art-163500] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=· neutral

Building a Resilient AI Text Humanizer with Dual-Engine Fallback (PHP & OpenRouter

A developer built a free AI text humanizer in vanilla PHP 8 that chains two free LLM providers, OpenRouter and SiliconFlow, so that a failed, rate-limited, or empty response from the first engine is transparently retried on the second. Each cURL call is capped at a 15-second timeout, and the fallback only triggers on non-200 status codes or empty output, keeping users from seeing 429 errors. The writeup also flags that polite free models tend to prepend conversational filler, which the prompt is written to suppress.

by read4 min views3 publishedNov 4, 2026

If you are building an AI-powered SaaS or a side project, you already know the pain: API downtime and rate limits.

Recently, I built a small, free webmaster toolbox (more on that later). One of the core features is an AI Text Humanizer that rewrites AI-generated text to bypass detectors like Turnitin or GPTZero.

Since I'm bootstrapping this, I relied on free AI models (like those on OpenRouter and SiliconFlow). The problem? Free tiers get heavily rate-limited. If a user hits "Submit" and the API returns a 429 Too Many Requests, a standard error message will immediately kill your conversion rate.

Here is how I built a seamless dual-engine fallback system using pure PHP (no heavy frameworks like Laravel, just vanilla PHP 8) to ensure 99% uptime for my users.

Instead of just calling one API endpoint, my backend logic acts as a traffic controller.

If Engine A takes too long, throws an error, or returns an empty response, the server instantly routes the exact same prompt to Engine B without the user ever knowing.

Here is the stripped-down version of my humanize.php logic.

The key is setting a strict CURLOPT_TIMEOUT. You don't want your user staring at a spinner for 30 seconds while Engine A hangs.

php
<?php
// Prevent timeout from killing the request
set_time_limit(60);

$inputText = $_POST['text'] ?? '';

if (empty($inputText)) {
    die(json_encode(['error' => 'No text provided']));
}

// The prompt (Keep it strict so it doesn't output "Sure, here is...")
$prompt = "Rewrite the following text to sound completely human, bypassing AI detection. Do not add any conversational filler. Output ONLY the rewritten text:\n\n" . $inputText;

// --- ENGINE 1: OpenRouter ---
$response = callAIEngine('openrouter', $prompt);

// --- ENGINE 2: SiliconFlow (Fallback) ---
if ($response === false || empty(trim($response))) {
    error_log("OpenRouter failed or rate-limited. Switching to SiliconFlow.");
    $response = callAIEngine('siliconflow', $prompt);
}

if ($response === false) {
    die(json_encode(['error' => 'Our AI engines are currently overloaded. Please try again in 5 minutes.']));
}

echo json_encode(['result' => $response]);

/**
 * The core cURL request handler
 */
function callAIEngine($engine, $prompt) {
    $config = [
        'openrouter' => [
            'url' => 'https://openrouter.ai/api/v1/chat/completions',
            'key' => 'YOUR_OPENROUTER_KEY',
            'model' => 'meta-llama/llama-3-8b-instruct:free' // Example free model
        ],
        'siliconflow' => [
            'url' => 'https://api.siliconflow.cn/v1/chat/completions',
            'key' => 'YOUR_SILICONFLOW_KEY',
            'model' => 'Qwen/Qwen2.5-7B-Instruct'
        ]
    ];

    $settings = $config[$engine];

    $data = [
        'model' => $settings['model'],
        'messages' => [
            ['role' => 'user', 'content' => $prompt]
        ],
        'temperature' => 0.7
    ];

    $ch = curl_init($settings['url']);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Authorization: Bearer ' . $settings['key']
    ]);

    // Crucial: Don't wait forever. 15 seconds max per engine.
    curl_setopt($ch, CURLOPT_TIMEOUT, 15);
    // Bypass SSL verification for cheap server environments (careful with this in prod)
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $result = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode !== 200 || !$result) {
        return false;
    }

    $json = json_decode($result, true);
    return $json['choices'][0]['message']['content'] ?? false;
}

The Two Biggest Pitfalls I Hit
1. The "Sure, here is your text" problem
Free models often try to be polite. If the user copies your output, they don't want to paste "Sure, here is the humanized version:" into their essay.
Fix: I had to aggressively tweak the system prompt, but sometimes models still do it. My frontend now uses a simple Regex to strip out the first line if it starts with conversational filler.

2. The Rate Limit Trap (IP Spam)
When you offer a free AI tool, botnets will find it. They will spam your API until your free quota is dead.
Fix: I implemented a strict IP-based limit (5 free uses per day) stored in a JSON flat-file (since I'm using vanilla PHP, no Redis). It's simple but effective. You can see how I handled the UX for this in my AI Humanizer tool here.

The Result
By wrapping the API calls in this fallback logic, my server can handle sudden spikes or model timeouts gracefully. The user gets their result, and I don't get angry emails about the tool being broken.

I've bundled this AI Humanizer along with 20+ other free developer tools (WHOIS, DNS, JSON formatter, port scanners) into a single, ad-free directory at Site Tools Box.

If you are building AI wrappers, I highly recommend implementing fallback logic early. It saves you a lot of debugging headaches later.

Happy coding!
── more in #ai-tools 4 stories · sorted by recency
── more on @openrouter 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/building-a-resilient…] indexed:0 read:4min 2026-11-04 · —