Skip to content
Finowl

PHP · Gender prediction

Predict gender from names in PHP 8 with cURL

In PHP, gender lookups are often used to enrich CRM records or to segment newsletter analytics. The name endpoint returns the prediction inside a data key, so after json_decode you read $result['data']['result_status'] first, then gender, confidence and source when the status is identified. A country code such as IT or US helps with names whose usage differs by country, like Andrea.

The example uses a PHP 8 match expression to turn the prediction into a human-readable line. Unknown results come back with gender set to null and a reason such as ambiguous or not_found, and the code prints that reason rather than guessing. Remember that unknown is a successful, charged response, so store it as unknown in your database and do not retry it.

Steps

  1. 1

    Enable cURL and export FINOWL_API_KEY for the PHP process.

  2. 2

    Call predictGender with a name and a two-letter country code, or null to omit it.

  3. 3

    Check result_status before reading gender, since unknown results have a null gender.

  4. 4

    Save confidence and source with each prediction so reports can filter on certainty.

Predict gender from names in PHP 8 with cURL
<?php

declare(strict_types=1);

function predictGender(string $name, ?string $country = null): array
{
    $payload = $country === null ? ['name' => $name] : ['name' => $name, 'country' => $country];
    for ($attempt = 0; $attempt < 3; $attempt++) {
        $retryAfter = 1;
        $ch = curl_init('https://api.finowl.co/v1/gender/name');
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . getenv('FINOWL_API_KEY'),
                'Content-Type: application/json',
            ],
            CURLOPT_POSTFIELDS => json_encode($payload, JSON_THROW_ON_ERROR),
            CURLOPT_HEADERFUNCTION => function ($ch, string $header) use (&$retryAfter): int {
                if (stripos($header, 'Retry-After:') === 0) {
                    $retryAfter = max(1, (int) trim(substr($header, 12)));
                }
                return strlen($header);
            },
        ]);
        $body = curl_exec($ch);
        if ($body === false) {
            throw new RuntimeException('Network error: ' . curl_error($ch));
        }
        $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
        $data = json_decode($body, true) ?? [];
        $code = $data['error']['code'] ?? 'unknown_error';
        if ($status === 200) {
            return $data['data'];
        }
        if ($status === 429 && $code === 'rate_limited') {
            sleep($retryAfter);
            continue;
        }
        throw match ($status) {
            400 => new InvalidArgumentException("Rejected input for {$name}: {$code}"),
            401 => new RuntimeException('Unauthorized: check FINOWL_API_KEY'),
            default => new RuntimeException("Finowl error {$status}: {$code}"),
        };
    }
    throw new RuntimeException('Still rate limited');
}

foreach ([['Andrea', 'IT'], ['Andrea', 'US'], ['Qwzx', null]] as [$name, $country]) {
    $p = predictGender($name, $country);
    $label = $name . ' (' . ($country ?? 'no country') . ')';
    echo match ($p['result_status']) {
        'unknown' => "{$label}: unknown, reason={$p['reason']}",
        default => "{$label}: {$p['gender']} confidence={$p['confidence']} source={$p['source']} country={$p['country']}",
    } . PHP_EOL;
}

IN PRODUCTION

Production tips

  • When enriching an existing table, send rows to /v1/gender/batch in groups of up to 50. Each batch counts as one request against the 60 requests per minute limit.

  • Leave ai_mode at its default of fallback unless you have a clear reason. Requesting AI on every lookup with always costs 3 credits instead of one.

  • Mention gender lookups in your privacy notice, use results only for aggregate analytics or low-stakes personalization, and give users a way to set their own gender in their profile.

Each lookup costs 1 credit (3 when it requests AI), with 100 free credits every month. See pricing and error codes.

A FEW GOOD QUESTIONS

Common questions

Predict gender from names in PHP 8 with cURL

Grab an API key, paste the example and run it. 100 free credits every month.