A PHP library to interact with the CoStar website through a shared Chrome session.
use Dprmc\CoStar\CoStarSpider;
use Dprmc\CoStar\Exception\CoStarLoginException;
$spider = new CoStarSpider($user, $pass, true);
try {
$spider->Login->login($user, $pass);
} catch (CoStarLoginException $exception) {
$spider->Debug->capture('login-exception');
}CoStarSpiderowns the sharedchrome-phpbrowser and current page.- Each site action lives in its own class under
src/Actions. - Actions receive the parent spider, which gives them shared access to the same browser, page, config, and debug tools.
DebugActioncaptures both screenshots and raw HTML for investigation.TwoFactorActionwrapsdprmc/gofer2faso email-delivered CoStar codes can be fetched through the spider.
Use the smoke runner to validate the real login flow against production with a dedicated test account.
cp .env.local.example .env.local
# edit .env.local with your credentials
composer smoke:loginThe Composer smoke script disables Composer's default 300-second process timeout, so long headed browser runs are not cut off early. You can also run the same flow directly with php bin/login-smoke.php.
Optional:
--debug-dir=/path/to/output: override the artifact directory--search-address="4170 Park Blvd San Diego, CA": run a live property-search smoke test after login--details-match-id="486603": fetch property-details GraphQL payloads for a specific MatchId after login--details-tabs="news": restrict property-details capture to specific tabsCOSTAR_CHROME_BIN=/path/to/chrome: force a specific Chrome binaryCOSTAR_SEARCH_ADDRESS="4170 Park Blvd San Diego, CA": env alternative for the search smoke testCOSTAR_DETAILS_MATCH_ID="486603": env alternative for the property-details smoke testCOSTAR_DETAILS_TABS="news": env alternative for restricting property-details tabsCOSTAR_CHROME_USER_DATA_DIR=/path/to/profile: persist Chrome cookies/session data between smoke runs
The smoke runner auto-loads .env.local if it exists. Shell environment variables still win if both are set.
The smoke runner always runs headed because CoStar login does not work in headless mode.
The smoke runner now defaults to a persistent Chrome profile under tmp/chrome-user-data, so CoStar cookies can survive between runs and reduce repeated 2FA challenges. If you want a different profile location, set COSTAR_CHROME_USER_DATA_DIR.
For email-backed 2FA retrieval, configure dprmc/gofer2fa through .env.local or the spider options. The spider now exposes:
$code = $spider->TwoFactor->waitForCode();Supported mailbox drivers in the spider config are:
office365_graphgmail_apiimappop3ses_s3
You can pass mailbox config in either of these shapes:
new CoStarSpider($user, $pass, true, [
'gofer2faConfig' => [
'mailbox' => [
'driver' => 'office365_graph',
'tenant' => '...',
'client_id' => '...',
'client_secret' => '...',
'mailbox_user' => 'inbox@example.com',
],
],
]);or the flatter backward-compatible shape:
new CoStarSpider($user, $pass, true, [
'gofer2faConfig' => [
'driver' => 'office365_graph',
'tenant' => '...',
'client_id' => '...',
'client_secret' => '...',
'mailbox_user' => 'inbox@example.com',
],
]);Examples:
composer smoke:login
composer smoke:login -- --debug-dir=/tmp/costar-smoke
composer smoke:login -- --search-address="4170 Park Blvd San Diego, CA"
composer smoke:login -- --details-match-id="486603"
composer smoke:login -- --details-match-id="486603" --details-tabs="news"