If this saves you time, a star on GitHub helps other PHP developers find it.
The unofficial PHP client for the Anthropic Claude API. Requires PHP 8.1+, Composer, and an Anthropic API key.
composer require claude-php/claude-php-sdk<?php
require 'vendor/autoload.php';
use ClaudePhp\ClaudePhp;
use ClaudePhp\Types\ModelParam;
$client = new ClaudePhp(apiKey: $_ENV['ANTHROPIC_API_KEY']);
$message = $client->messages()->create([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'max_tokens' => 1024,
'messages' => [
['role' => 'user', 'content' => 'Explain quantum entanglement in one paragraph.'],
],
]);
echo $message->content[0]['text'];The SDK reads ANTHROPIC_API_KEY from the environment automatically if you don't pass apiKey explicitly.
$stream = $client->messages()->stream([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'max_tokens' => 1024,
'messages' => [['role' => 'user', 'content' => 'Write a haiku about PHP.']],
]);
foreach ($stream as $event) {
if ($event['type'] === 'content_block_delta') {
echo $event['delta']['text'] ?? '';
}
}For helper methods over raw events, wrap the stream in MessageStream:
use ClaudePhp\Lib\Streaming\MessageStream;
use ClaudePhp\Responses\Helpers\StreamEventHelper;
$stream = new MessageStream($client->messages()->stream([...]));
foreach ($stream as $event) {
if (StreamEventHelper::isTextDelta($event)) {
echo StreamEventHelper::textDelta($event);
}
}
$final = $stream->getFinalMessage();See examples/streaming_comprehensive.php for all event types.
$messages = [
['role' => 'user', 'content' => 'My name is Alice.'],
['role' => 'assistant', 'content' => 'Nice to meet you, Alice!'],
['role' => 'user', 'content' => 'What is my name?'],
];
$response = $client->messages()->create([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'messages' => $messages,
]);Define tools with a name, description, and JSON Schema input definition. Claude calls them; your code runs them.
$response = $client->messages()->create([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'max_tokens' => 1024,
'tools' => [
[
'name' => 'get_weather',
'description' => 'Get current weather for a city.',
'input_schema' => [
'type' => 'object',
'properties' => ['city' => ['type' => 'string']],
'required' => ['city'],
],
],
],
'messages' => [['role' => 'user', 'content' => 'What is the weather in Tokyo?']],
]);
// When stop_reason === 'tool_use', execute the tool and send the result backFor automatic tool loop execution, use the built-in tool runner:
use function ClaudePhp\Lib\Tools\beta_tool;
$weather = beta_tool(
handler: fn($args) => "Sunny and 24°C in {$args['city']}",
name: 'get_weather',
description: 'Get current weather for a city.',
inputSchema: [
'type' => 'object', 'properties' => ['city' => ['type' => 'string']], 'required' => ['city'],
],
);
$result = $client->beta()->messages()->toolRunner([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'messages' => [['role' => 'user', 'content' => 'Weather in Tokyo?']],
], [$weather]);See examples/tool_use_overview.php for the full workflow.
Claude can reason step-by-step before answering. Three modes are available:
| Mode | Behaviour | When to use |
|---|---|---|
disabled |
No internal reasoning | Fast responses, simple prompts |
enabled |
Always reasons; set budget_tokens |
Deep analysis, guaranteed reasoning |
adaptive |
Model decides based on the prompt | Mixed workloads, cost-conscious |
// Adaptive — recommended for claude-opus-4-6
$response = $client->messages()->create([
'model' => ModelParam::MODEL_CLAUDE_OPUS_4_6,
'max_tokens' => 8192,
'thinking' => ['type' => 'adaptive'],
'messages' => [['role' => 'user', 'content' => 'Design a fault-tolerant distributed cache.']],
]);
foreach ($response->content as $block) {
if ($block['type'] === 'thinking') {
echo "Reasoning: " . $block['thinking'] . "\n";
} elseif ($block['type'] === 'text') {
echo $block['text'];
}
}See examples/extended_thinking.php and examples/adaptive_thinking.php.
Pass images as base64 or by URL. Pass PDFs or files via the Files API.
$response = $client->messages()->create([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'messages' => [
[
'role' => 'user',
'content' => [
[
'type' => 'image',
'source' => ['type' => 'base64', 'media_type' => 'image/jpeg', 'data' => $base64Data],
],
['type' => 'text', 'text' => 'What is in this image?'],
],
],
],
]);See examples/vision_comprehensive.php · examples/pdf_support.php · examples/files_api.php.
Process large numbers of requests at 50% of the standard cost, asynchronously.
$batch = $client->messages()->batches()->create([
'requests' => [
['custom_id' => 'req-1', 'params' => ['model' => ModelParam::MODEL_CLAUDE_SONNET_4_5, 'max_tokens' => 256, 'messages' => [...]]],
['custom_id' => 'req-2', 'params' => ['model' => ModelParam::MODEL_CLAUDE_SONNET_4_5, 'max_tokens' => 256, 'messages' => [...]]],
],
]);
// Poll until done
while ($batch->processing_status !== 'ended') {
sleep(5);
$batch = $client->messages()->batches()->retrieve($batch->id);
}
// Iterate JSONL results
foreach ($client->messages()->batches()->results($batch->id) as $result) {
echo $result['custom_id'] . ': ' . $result['result']['message']['content'][0]['text'] . "\n";
}See examples/batch_processing.php for the full workflow.
Get guaranteed JSON that matches a schema, without prompt engineering:
$schema = [
'type' => 'object',
'required' => ['name', 'price', 'quantity'],
'properties' => [
'name' => ['type' => 'string'],
'price' => ['type' => 'number'],
'quantity' => ['type' => 'integer'],
],
];
$parsed = $client->beta()->messages()->parse([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'max_tokens' => 256,
'messages' => [['role' => 'user', 'content' => 'I bought 3 coffees at $4.50 each.']],
'output_format' => $schema,
]);
// ['name' => 'coffee', 'price' => 4.5, 'quantity' => 3]See examples/structured_outputs.php.
These tools are executed by Anthropic's infrastructure — no handler code needed on your side.
Claude writes and runs sandboxed code, returning stdout, stderr, and generated files.
$response = $client->messages()->create([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'max_tokens' => 2048,
'tools' => [['name' => 'code_execution', 'type' => 'code_execution_20250825']],
'messages' => [['role' => 'user', 'content' => 'Compute the first 10 Fibonacci numbers.']],
]);Use code_execution_20260120 (beta) for REPL-state persistence across multiple tool calls.
Persistent file-based storage that survives across conversations.
$response = $client->messages()->create([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'tools' => [['name' => 'memory', 'type' => 'memory_20250818']],
'messages' => [['role' => 'user', 'content' => 'Remember: I prefer PHP 8.3 and UTC timezone.']],
]);Supports view, create, str_replace, insert, delete, and rename commands.
Retrieve live URL content with domain restrictions and token caps.
$response = $client->messages()->create([
'model' => ModelParam::MODEL_CLAUDE_SONNET_4_5,
'tools' => [
[
'name' => 'web_fetch',
'type' => 'web_fetch_20250910',
'allowed_domains' => ['docs.anthropic.com'],
'max_uses' => 3,
],
],
'messages' => [['role' => 'user', 'content' => 'Summarize https://docs.anthropic.com/']],
]);See examples/code_execution.php · examples/memory_tool.php · examples/web_fetch.php.
use ClaudePhp\Types\ModelParam;| Constant | Model ID | Best for |
|---|---|---|
MODEL_CLAUDE_OPUS_4_6 |
claude-opus-4-6 |
Frontier reasoning, adaptive thinking |
MODEL_CLAUDE_SONNET_4_6 |
claude-sonnet-4-6 |
Balanced capability and speed |
MODEL_CLAUDE_SONNET_4_5 |
claude-sonnet-4-5-20250929 |
Coding, complex reasoning |
MODEL_CLAUDE_HAIKU_4_5 |
claude-haiku-4-5-20251001 |
Speed and cost efficiency |
MODEL_CLAUDE_3_7_SONNET_LATEST |
claude-3-7-sonnet-latest |
Hybrid reasoning |
MODEL_CLAUDE_3_5_HAIKU_LATEST |
claude-3-5-haiku-latest |
Ultra-fast responses |
Use *_LATEST aliases for automatic updates, or dated IDs (e.g. MODEL_CLAUDE_SONNET_4_5) for pinned deployments. See src/Types/ModelParam.php for the full list.
$client = new ClaudePhp(
apiKey: $_ENV['ANTHROPIC_API_KEY'], // defaults to ANTHROPIC_API_KEY env var
baseUrl: 'https://api.anthropic.com/v1',
timeout: 30.0, // seconds
maxRetries: 2, // auto-retries on 429 / 5xx
customHeaders: ['X-My-Header' => 'value'],
);// OAuth2 / Bearer token (e.g. enterprise SSO, proxies)
$client = new ClaudePhp(apiKey: null, customHeaders: [
'Authorization' => 'Bearer your-token',
]);
// Custom x-api-key (e.g. API gateway with key management)
$client = new ClaudePhp(apiKey: null, customHeaders: [
'x-api-key' => 'your-gateway-key',
]);See examples/authentication_flexibility.php.
use ClaudePhp\Exceptions\{AuthenticationError, RateLimitError, APIConnectionError, APIStatusError};
try {
$response = $client->messages()->create([...]);
} catch (AuthenticationError $e) {
// Invalid or missing API key
} catch (RateLimitError $e) {
$retryAfter = $e->response->getHeaderLine('retry-after');
// Back off and retry
} catch (APIConnectionError $e) {
// Network or timeout failure
} catch (APIStatusError $e) {
echo "HTTP {$e->status_code}: {$e->message}";
}Retries on 429 and 5xx responses happen automatically (configurable via maxRetries). See examples/error_handling.php.
Install the first-party package for service provider, facade, and config publishing:
composer require claude-php/claude-php-sdk-laraveluse ClaudePhp\Laravel\Facades\Claude;
$response = Claude::messages()->create([...]);For manual registration without the package:
// app/Providers/ClaudeServiceProvider.php
$this->app->singleton(ClaudePhp::class, fn() => new ClaudePhp(
apiKey: config('services.claude.api_key'),
maxRetries: config('services.claude.max_retries', 2),
));# config/services.yaml
services:
ClaudePhp\ClaudePhp:
arguments:
$apiKey: "%env(ANTHROPIC_API_KEY)%"
$maxRetries: 2| Platform | Class | Example |
|---|---|---|
| Microsoft Azure AI Foundry | ClaudePhp\Lib\Foundry\AnthropicFoundry |
examples/foundry.php |
| AWS Bedrock | ClaudePhp\Lib\Bedrock\AnthropicBedrock |
— |
| Google Vertex AI | ClaudePhp\Lib\Vertex\AnthropicVertex |
— |
85+ runnable examples organised by topic — streaming, vision, tool use, batching, prompt caching, context management, and more:
examples/ — see examples/README.md for the full index
tutorials/ — 17 progressive tutorials from "Hello Claude" to autonomous agents
Highlights:
- examples/quickstart.php — 10-line hello world
- examples/streaming_comprehensive.php — all streaming patterns
- examples/tool_use_overview.php — full tool use workflow
- examples/extended_thinking.php — thinking budgets and modes
- examples/prompt_caching.php — 90% cost reduction on repeated context
- examples/batch_processing.php — 50% cost savings at scale
- tutorials/README.md — start the agentic AI tutorial series
composer install # install dependencies
composer test # PHPUnit (351 tests, 1002 assertions)
composer lint # PSR-12 style check
composer format # auto-fix style
composer stan # PHPStan static analysissrc/
ClaudePhp.php main client
Resources/ Messages, Batches, Models, Files, Beta
Types/ ModelParam constants, tool param types
Responses/ response objects and helpers
Exceptions/ exception hierarchy
Lib/ streaming, tool runner, structured outputs
tests/
Integration/ mocked HTTP end-to-end tests
Unit/ unit tests per component
examples/ 85+ runnable scripts
tutorials/ 17 agentic AI tutorials
- Fork and clone the repo
- Run
composer install - Make your changes, add tests
- Ensure
composer test,composer lint, andcomposer stanall pass - Open a pull request
This SDK was built independently by Dale Hurley to give the PHP community a first-class Claude integration — the same one the Python and TypeScript communities already enjoy. It tracks the official API closely, ships 85+ examples covering every docs page, and has a full tutorial series for building agentic systems.
If you work at Anthropic and would like to sponsor, officially adopt, or collaborate on this project, I'd love to hear from you. Reach out via GitHub Discussions or the email in my profile.
MIT — see LICENSE