{"id":37983484,"url":"https://github.com/browserbase/stagehand-php","last_synced_at":"2026-01-29T21:15:46.189Z","repository":{"id":329006427,"uuid":"1117194714","full_name":"browserbase/stagehand-php","owner":"browserbase","description":"🐘 [ALPHA] Official Stagehand AI Browser Automation SDK for PHP users. Built by Browserbase.com","archived":false,"fork":false,"pushed_at":"2026-01-21T03:05:48.000Z","size":321,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-21T04:44:08.690Z","etag":null,"topics":["ai","browser-automation","browserbase","php","stagehand"],"latest_commit_sha":null,"homepage":"https://stagehand.stldocs.app/api","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/browserbase.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-16T01:04:08.000Z","updated_at":"2026-01-21T03:05:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/browserbase/stagehand-php","commit_stats":null,"previous_names":["browserbase/stagehand-php"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/browserbase/stagehand-php","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/browserbase","download_url":"https://codeload.github.com/browserbase/stagehand-php/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/browserbase%2Fstagehand-php/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28885357,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-29T21:06:44.224Z","status":"ssl_error","status_checked_at":"2026-01-29T21:06:42.160Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","browser-automation","browserbase","php","stagehand"],"created_at":"2026-01-16T18:37:22.553Z","updated_at":"2026-01-29T21:15:46.180Z","avatar_url":"https://github.com/browserbase.png","language":"PHP","readme":"\u003c!-- x-stagehand-custom-start --\u003e\n\u003cdiv id=\"toc\" align=\"center\" style=\"margin-bottom: 0;\"\u003e\n  \u003cul style=\"list-style: none; margin: 0; padding: 0;\"\u003e\n    \u003ca href=\"https://stagehand.dev\"\u003e\n      \u003cpicture\u003e\n        \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_logo.png\" /\u003e\n        \u003cimg alt=\"Stagehand\" src=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_logo.png\" width=\"200\" style=\"margin-right: 30px;\" /\u003e\n      \u003c/picture\u003e\n    \u003c/a\u003e\n  \u003c/ul\u003e\n\u003c/div\u003e\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eThe AI Browser Automation Framework\u003c/strong\u003e\u003cbr\u003e\n  \u003c!--\u003ca href=\"https://docs.stagehand.dev/v3/sdk/php\"\u003eRead the Docs\u003c/a\u003e--\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/browserbase/stagehand/tree/main?tab=MIT-1-ov-file#MIT-1-ov-file\"\u003e\n    \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_license.svg\" /\u003e\n      \u003cimg alt=\"MIT License\" src=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_license.svg\" /\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://stagehand.dev/discord\"\u003e\n    \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/dark_discord.svg\" /\u003e\n      \u003cimg alt=\"Discord Community\" src=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/light_discord.svg\" /\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://trendshift.io/repositories/12122\" target=\"_blank\"\u003e\u003cimg src=\"https://trendshift.io/api/badge/repositories/12122\" alt=\"browserbase%2Fstagehand | Trendshift\" style=\"width: 250px; height: 55px;\" width=\"250\" height=\"55\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\nIf you're looking for other languages, you can find them\n\u003ca href=\"https://docs.stagehand.dev/v3/first-steps/introduction\"\u003e here\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\" style=\"display: flex; align-items: center; justify-content: center; gap: 4px; margin-bottom: 0;\"\u003e\n  \u003cb\u003eVibe code\u003c/b\u003e\n  \u003cspan style=\"font-size: 1.05em;\"\u003e Stagehand with \u003c/span\u003e\n  \u003ca href=\"https://director.ai\" style=\"display: flex; align-items: center;\"\u003e\n    \u003cspan\u003eDirector\u003c/span\u003e\n  \u003c/a\u003e\n  \u003cspan\u003e \u003c/span\u003e\n  \u003cpicture\u003e\n    \u003cimg alt=\"Director\" src=\"https://raw.githubusercontent.com/browserbase/stagehand/main/media/director_icon.svg\" width=\"25\" /\u003e\n  \u003c/picture\u003e\n\u003c/div\u003e\n\n## What is Stagehand?\n\nStagehand is a browser automation framework used to control web browsers with natural language and code. By combining the power of AI with the precision of code, Stagehand makes web automation flexible, maintainable, and actually reliable.\n\n## Why Stagehand?\n\nMost existing browser automation tools either require you to write low-level code in a framework like Selenium, Playwright, or Puppeteer, or use high-level agents that can be unpredictable in production. By letting developers choose what to write in code vs. natural language (and bridging the gap between the two) Stagehand is the natural choice for browser automations in production.\n\n1. **Choose when to write code vs. natural language**: use AI when you want to navigate unfamiliar pages, and use code when you know exactly what you want to do.\n\n2. **Go from AI-driven to repeatable workflows**: Stagehand lets you preview AI actions before running them, and also helps you easily cache repeatable actions to save time and tokens.\n\n3. **Write once, run forever**: Stagehand's auto-caching combined with self-healing remembers previous actions, runs without LLM inference, and knows when to involve AI whenever the website changes and your automation breaks.\n\u003c!-- x-stagehand-custom-end --\u003e\n\n# Stagehand PHP API library\n\nThe Stagehand PHP library provides convenient access to the Stagehand REST API from any PHP 8.1.0+ application.\n\nIt is generated with [Stainless](https://www.stainless.com/).\n\n## Documentation\n\nThe REST API documentation can be found on [docs.stagehand.dev](https://docs.stagehand.dev).\n\n## Installation\n\n\u003c!-- x-release-please-start-version --\u003e\n\n```\ncomposer require \"browserbase/stagehand 3.10.0\"\n```\n\n\u003c!-- x-release-please-end --\u003e\n\n## Usage\n\nThis library uses named parameters to specify optional arguments.\nParameters with a default value must be set by name.\n\nHere's a comprehensive example demonstrating the full workflow: start session, navigate, observe, act, extract, execute agent, and end session.\n\n```php\n\u003c?php\n\nrequire_once __DIR__ . '/../vendor/autoload.php';\n\nuse Stagehand\\Client;\nuse Stagehand\\Sessions\\Action;\n\n// Load environment variables from .env file if it exists\nif (file_exists(__DIR__ . '/../.env')) {\n    $dotenv = parse_ini_file(__DIR__ . '/../.env');\n    foreach ($dotenv as $key =\u003e $value) {\n        if (!getenv($key)) {\n            putenv(\"$key=$value\");\n        }\n    }\n}\n\n// Initialize the Stagehand client with API keys from environment variables\n$client = new Client(\n    browserbaseAPIKey: getenv('BROWSERBASE_API_KEY') ?: throw new Exception('BROWSERBASE_API_KEY environment variable is required'),\n    browserbaseProjectID: getenv('BROWSERBASE_PROJECT_ID') ?: throw new Exception('BROWSERBASE_PROJECT_ID environment variable is required'),\n    modelAPIKey: getenv('MODEL_API_KEY') ?: throw new Exception('MODEL_API_KEY environment variable is required'),\n);\n\n// Start a new session\n$startResponse = $client-\u003esessions-\u003estart(\n    browserbaseAPIKey: getenv('BROWSERBASE_API_KEY'),\n    browserbaseProjectID: getenv('BROWSERBASE_PROJECT_ID'),\n    model: 'openai/gpt-4o',\n);\necho \"Session started: {$startResponse-\u003edata-\u003esessionID}\\n\";\n\n$sessionID = $startResponse-\u003edata-\u003esessionID;\n\n// Navigate to Hacker News\n$client-\u003esessions-\u003enavigate(\n    $sessionID,\n    url: 'https://news.ycombinator.com',\n);\necho \"Navigated to Hacker News\\n\";\n\n// Observe to find possible actions\n$observeResponse = $client-\u003esessions-\u003eobserve(\n    $sessionID,\n    instruction: 'find the link to view comments for the top post',\n);\n\n$actions = $observeResponse-\u003edata-\u003eresult;\necho \"Found \" . count($actions) . \" possible actions\\n\";\n\nif (count($actions) === 0) {\n    echo \"No actions found\\n\";\n    exit(0);\n}\n\n// Use the first action\n$action = $actions[0];\necho \"Acting on: {$action-\u003edescription}\\n\";\n\n// Pass the action to Act\n$actResponse = $client-\u003esessions-\u003eact(\n    $sessionID,\n    input: Action::with(\n        description: $action-\u003edescription,\n        selector: $action-\u003eselector,\n        method: $action-\u003emethod,\n        arguments: $action-\u003earguments,\n    ),\n);\necho \"Act completed: {$actResponse-\u003edata-\u003eresult-\u003emessage}\\n\";\n\n// Extract data from the page\n// We're now on the comments page, so extract the top comment text\n$extractResponse = $client-\u003esessions-\u003eextract(\n    $sessionID,\n    instruction: 'extract the text of the top comment on this page',\n    schema: [\n        'type' =\u003e 'object',\n        'properties' =\u003e [\n            'commentText' =\u003e [\n                'type' =\u003e 'string',\n                'description' =\u003e 'The text content of the top comment',\n            ],\n            'author' =\u003e [\n                'type' =\u003e 'string',\n                'description' =\u003e 'The username of the comment author',\n            ],\n        ],\n        'required' =\u003e ['commentText'],\n    ],\n);\necho \"Extracted data: \" . json_encode($extractResponse-\u003edata-\u003eresult) . \"\\n\";\n\n// Get the author from the extracted data\n$extractedData = $extractResponse-\u003edata-\u003eresult;\n$author = $extractedData['author'] ?? 'unknown';\necho \"Looking up profile for author: $author\\n\";\n\n// Use the Agent to find the author's profile\n// Execute runs an autonomous agent that can navigate and interact with pages\n$executeResponse = $client-\u003esessions-\u003eexecuteAgent(\n    $sessionID,\n    agentConfig: [\n        'model' =\u003e 'openai/gpt-4.1-mini',\n        'cua' =\u003e false,\n    ],\n    executeOptions: [\n        'instruction' =\u003e \"Find any personal website, GitHub, LinkedIn, or other best profile URL for the Hacker News user '$author'. \" .\n            \"Click on their username to go to their profile page and look for any links they have shared. \" .\n            \"Use Google Search with their username or other details from their profile if you dont find any direct links.\",\n        'maxSteps' =\u003e 15,\n    ],\n);\necho \"Agent completed: {$executeResponse-\u003edata-\u003eresult-\u003emessage}\\n\";\necho \"Agent success: \" . ($executeResponse-\u003edata-\u003eresult-\u003esuccess ? 'true' : 'false') . \"\\n\";\necho \"Agent actions taken: \" . count($executeResponse-\u003edata-\u003eresult-\u003eactions) . \"\\n\";\n\n// End the session to clean up resources\n$client-\u003esessions-\u003eend($sessionID);\necho \"Session ended\\n\";\n```\n\n### Running the Example\n\nSet the required environment variables and run the example script:\n\n```bash\n# Set your credentials\nexport BROWSERBASE_API_KEY=\"your-browserbase-api-key\"\nexport BROWSERBASE_PROJECT_ID=\"your-browserbase-project-id\"\nexport MODEL_API_KEY=\"your-openai-api-key\"\n\n# Install dependencies and run\ncomposer install\nphp examples/basic.php\n```\n\n### Value Objects\n\nIt is recommended to use the static `with` constructor `Action::with(description: 'Click the submit button', ...)`\nand named parameters to initialize value objects.\n\nHowever, builders are also provided `(new Action)-\u003ewithDescription('Click the submit button')`.\n\n### Streaming\n\nWe provide support for streaming responses using Server-Sent Events (SSE).\n\n```php\n\u003c?php\n\nuse Stagehand\\Client;\n\n$client = new Client(\n  browserbaseAPIKey: getenv('BROWSERBASE_API_KEY') ?: 'My Browserbase API Key',\n  browserbaseProjectID: getenv(\n    'BROWSERBASE_PROJECT_ID'\n  ) ?: 'My Browserbase Project ID',\n  modelAPIKey: getenv('MODEL_API_KEY') ?: 'My Model API Key',\n);\n\n$stream = $client-\u003esessions-\u003eactStream(\n  '00000000-your-session-id-000000000000',\n  input: 'click the first link on the page',\n);\n\nforeach ($stream as $response) {\n  var_dump($response);\n}\n```\n\n### Handling errors\n\nWhen the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `Stagehand\\Core\\Exceptions\\APIException` will be thrown:\n\n```php\n\u003c?php\n\nuse Stagehand\\Core\\Exceptions\\APIConnectionException;\nuse Stagehand\\Core\\Exceptions\\RateLimitException;\nuse Stagehand\\Core\\Exceptions\\APIStatusException;\n\ntry {\n  $response = $client-\u003esessions-\u003estart(modelName: 'openai/gpt-5-nano');\n} catch (APIConnectionException $e) {\n  echo \"The server could not be reached\", PHP_EOL;\n  var_dump($e-\u003egetPrevious());\n} catch (RateLimitException $e) {\n  echo \"A 429 status code was received; we should back off a bit.\", PHP_EOL;\n} catch (APIStatusException $e) {\n  echo \"Another non-200-range status code was received\", PHP_EOL;\n  echo $e-\u003egetMessage();\n}\n```\n\nError codes are as follows:\n\n| Cause            | Error Type                     |\n| ---------------- | ------------------------------ |\n| HTTP 400         | `BadRequestException`          |\n| HTTP 401         | `AuthenticationException`      |\n| HTTP 403         | `PermissionDeniedException`    |\n| HTTP 404         | `NotFoundException`            |\n| HTTP 409         | `ConflictException`            |\n| HTTP 422         | `UnprocessableEntityException` |\n| HTTP 429         | `RateLimitException`           |\n| HTTP \u003e= 500      | `InternalServerException`      |\n| Other HTTP error | `APIStatusException`           |\n| Timeout          | `APITimeoutException`          |\n| Network error    | `APIConnectionException`       |\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\n\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, \u003e=500 Internal errors, and timeouts will all be retried by default.\n\nYou can use the `maxRetries` option to configure or disable this:\n\n```php\n\u003c?php\n\nuse Stagehand\\Client;\n\n// Configure the default for all requests:\n$client = new Client(requestOptions: ['maxRetries' =\u003e 0]);\n\n// Or, configure per-request:\n$result = $client-\u003esessions-\u003estart(\n  modelName: 'openai/gpt-5-nano', requestOptions: ['maxRetries' =\u003e 5]\n);\n```\n\n## Advanced concepts\n\n### Making custom or undocumented requests\n\n#### Undocumented properties\n\nYou can send undocumented parameters to any endpoint, and read undocumented response properties, like so:\n\nNote: the `extra*` parameters of the same name overrides the documented parameters.\n\n```php\n\u003c?php\n\n$response = $client-\u003esessions-\u003estart(\n  modelName: 'openai/gpt-5-nano',\n  requestOptions: [\n    'extraQueryParams' =\u003e ['my_query_parameter' =\u003e 'value'],\n    'extraBodyParams' =\u003e ['my_body_parameter' =\u003e 'value'],\n    'extraHeaders' =\u003e ['my-header' =\u003e 'value'],\n  ],\n);\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a request, as seen in the examples above.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints while retaining the benefit of auth, retries, and so on, you can make requests using `client.request`, like so:\n\n```php\n\u003c?php\n\n$response = $client-\u003erequest(\n  method: \"post\",\n  path: '/undocumented/endpoint',\n  query: ['dog' =\u003e 'woof'],\n  headers: ['useful-header' =\u003e 'interesting-value'],\n  body: ['hello' =\u003e 'world']\n);\n```\n\n## Versioning\n\nThis package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the library is in initial development and has a major version of `0`, APIs may change at any time.\n\nThis package considers improvements to the (non-runtime) PHPDoc type definitions to be non-breaking changes.\n\n## Requirements\n\nPHP 8.1.0 or higher.\n\n## Contributing\n\nSee [the contributing documentation](https://github.com/browserbase/stagehand-php/tree/main/CONTRIBUTING.md).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrowserbase%2Fstagehand-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrowserbase%2Fstagehand-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrowserbase%2Fstagehand-php/lists"}