Claude API PHP Example

Working PHP code for calling the Claude API using cURL and Guzzle. No official PHP SDK needed — these copy-paste examples work with Laravel, WordPress, and plain PHP scripts.

💥 50p impulse-buy: Power Prompts PDF (first 10 buyers) 30 battle-tested Claude Code prompts · 8-page PDF · paste into CLAUDE.md and never re-type a prompt again · 50p impulse-buy, no commitment

PHP has no official Anthropic SDK, so the standard approach is to call the REST API via cURL or Guzzle. These examples work in plain PHP 8+, Laravel, Symfony, and WordPress.

Minimal cURL example

<?php
function claude(string $prompt, string $model = "claude-sonnet-4-6", int $maxTokens = 1024): string {
    $ch = curl_init("https://api.anthropic.com/v1/messages");
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST           => true,
        CURLOPT_HTTPHEADER     => [
            "x-api-key: " . getenv("ANTHROPIC_API_KEY"),
            "anthropic-version: 2023-06-01",
            "content-type: application/json",
        ],
        CURLOPT_POSTFIELDS => json_encode([
            "model"      => $model,
            "max_tokens" => $maxTokens,
            "messages"   => [["role" => "user", "content" => $prompt]],
        ]),
    ]);
    $response = curl_exec($ch);
    curl_close($ch);
    return json_decode($response, true)["content"][0]["text"];
}

echo claude("Explain PHP 8 fibers in one paragraph.");

With system prompt

$body = json_encode([
    "model"      => "claude-sonnet-4-6",
    "max_tokens" => 512,
    "system"     => "You are a concise PHP expert. Respond in bullet points.",
    "messages"   => [["role" => "user", "content" => "What is the difference between abstract classes and interfaces in PHP?"]],
]);

Reusable ClaudeClient class

<?php
class ClaudeClient {
    private string $apiKey;
    private string $model;
    const BASE_URL = "https://api.anthropic.com/v1/messages";

    public function __construct(string $apiKey = "", string $model = "claude-sonnet-4-6") {
        $this->apiKey = $apiKey ?: getenv("ANTHROPIC_API_KEY");
        $this->model  = $model;
    }

    public function chat(array $messages, ?string $system = null, int $maxTokens = 1024): string {
        $body = ["model" => $this->model, "max_tokens" => $maxTokens, "messages" => $messages];
        if ($system) $body["system"] = $system;

        $ch = curl_init(self::BASE_URL);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST           => true,
            CURLOPT_HTTPHEADER     => $this->headers(),
            CURLOPT_POSTFIELDS     => json_encode($body),
        ]);

        $res  = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($code !== 200) throw new RuntimeException("Claude API error $code: $res");
        return json_decode($res, true)["content"][0]["text"];
    }

    private function headers(): array {
        return [
            "x-api-key: " . $this->apiKey,
            "anthropic-version: 2023-06-01",
            "content-type: application/json",
        ];
    }
}

$client = new ClaudeClient();
echo $client->chat([["role" => "user", "content" => "Write a PHP function to sanitize user input."]]);

Streaming response

<?php
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");

$body = json_encode([
    "model"      => "claude-sonnet-4-6",
    "max_tokens" => 1024,
    "stream"     => true,
    "messages"   => [["role" => "user", "content" => "Write a tutorial on PHP 8 match expressions."]],
]);

$buffer = "";
$ch = curl_init("https://api.anthropic.com/v1/messages");
curl_setopt_array($ch, [
    CURLOPT_POST       => true,
    CURLOPT_HTTPHEADER => [
        "x-api-key: " . getenv("ANTHROPIC_API_KEY"),
        "anthropic-version: 2023-06-01",
        "content-type: application/json",
    ],
    CURLOPT_POSTFIELDS    => $body,
    CURLOPT_WRITEFUNCTION => function ($ch, $chunk) use (&$buffer) {
        $buffer .= $chunk;
        while (($pos = strpos($buffer, "
")) !== false) {
            $line   = substr($buffer, 0, $pos);
            $buffer = substr($buffer, $pos + 1);
            if (!str_starts_with($line, "data: ")) continue;
            $data = json_decode(substr($line, 6), true);
            if ($data["type"] ?? "" === "content_block_delta") {
                echo "data: " . json_encode(["text" => $data["delta"]["text"]]) . "

";
                ob_flush(); flush();
            }
        }
        return strlen($chunk);
    },
]);
curl_exec($ch);
curl_close($ch);

Guzzle example (Laravel / Composer projects)

// composer require guzzlehttp/guzzle
use GuzzleHttpClient;

$http = new Client(["base_uri" => "https://api.anthropic.com"]);
$res  = $http->post("/v1/messages", [
    "headers" => [
        "x-api-key"         => env("ANTHROPIC_API_KEY"),
        "anthropic-version" => "2023-06-01",
    ],
    "json" => [
        "model"      => "claude-sonnet-4-6",
        "max_tokens" => 1024,
        "messages"   => [["role" => "user", "content" => "Explain Laravel service containers."]],
    ],
]);
$reply = json_decode($res->getBody(), true)["content"][0]["text"];

WordPress integration

// wp-config.php
define('ANTHROPIC_API_KEY', 'sk-ant-...');

// functions.php or plugin
function claude_wp(string $prompt): string {
    $response = wp_remote_post("https://api.anthropic.com/v1/messages", [
        "headers" => [
            "x-api-key"         => ANTHROPIC_API_KEY,
            "anthropic-version" => "2023-06-01",
            "content-type"      => "application/json",
        ],
        "body"    => json_encode([
            "model"      => "claude-sonnet-4-6",
            "max_tokens" => 512,
            "messages"   => [["role" => "user", "content" => $prompt]],
        ]),
        "timeout" => 30,
    ]);
    return json_decode(wp_remote_retrieve_body($response), true)["content"][0]["text"];
}

cURL vs Guzzle — when to use each

ScenarioRecommendationReason
Plain PHP / no ComposercURLBuilt-in, zero dependencies
Laravel / Symfony projectGuzzle or Http facadeAlready a dependency; cleaner async support
WordPress pluginwp_remote_post()Respects WordPress HTTP filters and caching
Streaming to browsercURL WRITEFUNCTIONLowest overhead for chunked writes
Retry / concurrencyGuzzle + RetryMiddlewareBuilt-in middleware stack

To estimate costs for your PHP application, use the Claude API Cost Calculator. For model pricing details, see the Anthropic API pricing guide.

Frequently asked questions

Is there an official Anthropic PHP SDK?
Not as of mid-2026. Use PHP's built-in cURL extension or Guzzle HTTP client to call the REST API directly. Both approaches are shown below.
How do I stream Claude responses in PHP?
Set CURLOPT_WRITEFUNCTION and parse each SSE chunk as it arrives. Flush output with `ob_flush()` and `flush()` to push each token to the browser in real time.
Can I use Claude in WordPress?
Yes. Call the API via wp_remote_post() or cURL from a plugin or functions.php. Store the API key in wp-config.php as a constant, not hardcoded in the plugin.
Does this work with Laravel?
Yes. Add the ClaudeClient class to app/Services/ and bind it in a service provider. Use Laravel's Http facade or Guzzle for a cleaner integration.
Which model should I use?
claude-sonnet-4-6 for most tasks. claude-haiku-4-5-20251001 for high-volume cheap requests like moderation or classification. claude-opus-4-7 for complex reasoning tasks.

Free tools

Cost Calculator → API Cookbook → Diff Summarizer → Skills Browser →

More examples

Claude API Python QuickstartClaude API Node.js / TypeScript QuickstartClaude API Streaming in PythonClaude API Streaming in Node.js / TypeScriptClaude API Tool Use in PythonClaude API Tool Use in Node.js / TypeScript