Back to Articles

Controlling Nest Thermostats with Reverse-Engineered PHP: Inside the Unofficial API

[ View on GitHub ]

Controlling Nest Thermostats with Reverse-Engineered PHP: Inside the Unofficial API

Hook

When Google closed Nest’s public API program to new developers in 2019, thousands of home automation enthusiasts suddenly had no official way to integrate their $250 thermostats with their own code. The community’s answer? Reverse-engineer the private APIs that Nest’s own mobile apps use.

Context

The Nest Learning Thermostat became a poster child for the smart home revolution, but Google’s approach to third-party developers has been inconsistent at best. The original Nest Developer Program offered a REST API with OAuth authentication, but in 2019 Google stopped accepting new developer registrations, promising migration to the Device Access program with a $5 fee and stricter approval processes. For hobbyists wanting to write simple scripts to control their own thermostats, for PHP developers maintaining legacy home automation systems, or for anyone who couldn’t justify the bureaucratic overhead of official API access, this created a frustrating gap.

The gboudreau/nest-api library fills that gap by doing what Nest’s own mobile and web applications do: speaking directly to Nest’s private backend APIs. It’s a single PHP class that handles authentication, session management, and wraps the undocumented HTTP endpoints that Nest uses internally. Created before official APIs existed and maintained as those APIs became harder to access, it represents the pragmatic hacker ethos of “if they won’t give us an API, we’ll use the one they use themselves.” With nearly 300 GitHub stars, it’s become a go-to solution for PHP-based home automation projects that need Nest integration without the enterprise overhead.

Technical Insight

instantiate with credentials

check cache

session valid

session expired

session expired

POST credentials

POST tokens

session token

authenticated requests

JSON responses

device state & control

PHP Application

Nest Class

Session Cache

Legacy Auth

email/password

Google Auth

issue_token/cookies

Nest JSON APIs

System architecture — auto-generated

At its core, nest-api is a well-designed PHP class that acts as an HTTP client wrapper around Nest’s undocumented JSON APIs. The architecture is straightforward: authenticate once, cache the session, then make authenticated requests to specific endpoints for different operations. What makes it interesting is how it handles the authentication complexity that Nest has layered on over the years.

The library supports two authentication paths. The legacy approach uses traditional Nest credentials (email and password), which worked beautifully until Google started migrating accounts. The modern approach requires manually extracting an issue_token and browser cookies from an authenticated Nest web session—a clunky but necessary workaround for Google-migrated accounts. Here’s what basic usage looks like:

<?php
require_once('nest.class.php');

// Authentication with Google account tokens (modern approach)
$nest = new Nest(
    null,  // no username for Google accounts
    null,  // no password for Google accounts  
    'https://accounts.google.com/o/oauth2/iframerpc?action=issueToken...',
    'COOKIE_CONTENT_HERE'
);

// Get current temperature
$temp = $nest->getTargetTemperature();
echo "Current target: {$temp}°F\n";

// Adjust temperature
$nest->setTargetTemperature(72);

// Set away mode
$nest->setAway(true);

// Access energy history
$energy = $nest->getEnergyLatest();
echo "Recent energy usage: " . json_encode($energy) . "\n";

Under the hood, the class maintains state by caching the authentication session to disk (using file_get_contents and file_put_contents), which prevents hammering Nest’s login endpoints with every script execution. This is smarter than it looks—Nest’s backend can rate-limit or block accounts that authenticate too frequently, a protection mechanism against credential stuffing attacks that inadvertently catches poorly-designed API clients.

The request architecture reveals how Nest’s internal APIs are structured. Temperature changes don’t go to a simple REST endpoint like /api/thermostat/123/temperature. Instead, they’re sent as JSON payloads to transport URLs that look like /v2/put/shared.{SERIAL}, with the actual command nested inside JSON structures that mirror Nest’s internal data model. The library abstracts this complexity:

public function setTargetTemperature($temp, $scale = null) {
    $scale = $scale ?: $this->getTemperatureScale();
    $temp = $this->temperatureInCelsius($temp, $scale);
    
    return $this->setSharedData([
        'target_temperature' => round($temp, 1)
    ]);
}

private function setSharedData($data) {
    $url = $this->transport_url . '/v2/put/shared.' . $this->serial_number;
    return $this->sendRequest($url, $data);
}

Notice how it converts temperatures to Celsius internally regardless of what the user specifies—this reveals that Nest’s backend always works in metric, with localization handled client-side. The library also exposes more advanced features like schedule manipulation, humidity reading, fan control, and even Nest Protect smoke detector status. It parses complex JSON responses from endpoints like /v2/mobile/user.{USER_ID} that return the entire device state tree, then provides clean getter methods that extract specific values.

One clever design decision is how the class handles multiple thermostats. The constructor can take a device serial number to target a specific unit, but if you omit it, methods like setTargetTemperature() operate on the first thermostat found in your account. For single-thermostat households (the majority), this means less boilerplate. For multi-zone setups, you instantiate multiple objects with different serial numbers.

The session caching mechanism deserves attention for what it teaches about API client design. Rather than storing just an auth token, the class serializes its entire internal state—the authenticated HTTP cookie jar, device metadata, user information—into a JSON file. This means subsequent script runs skip not just login but also the device enumeration requests, reducing a cold start from 3-4 HTTP requests down to zero for cached sessions. The cache respects expiration, automatically re-authenticating when sessions age out.

Gotcha

The elephant in the room is that this entire library depends on undocumented, unsupported APIs that Google/Nest can break without notice. And they do break—the README documents multiple authentication changes over the years, from simple username/password to the current cookie-extraction dance. Each time Nest refactors their mobile app’s backend communication, this library needs updates. If you deploy this in a production setting and Nest changes an endpoint structure or authentication flow, your application stops working until the maintainer (or you) reverse-engineer the new implementation.

The Google account authentication process borders on user-hostile for non-technical users. You need to open Chrome DevTools, log into the Nest website, execute JavaScript in the console to extract an issue_token, then copy entire cookie headers into your configuration. This works fine for developers automating their own homes, but it’s completely impractical for any application with end users. You can’t programmatically obtain these tokens without effectively simulating a full browser session, which would require headless browser automation—at which point you’re building a fragile house of cards. The security implications are also concerning: these tokens and cookies provide full account access, so they need to be stored as securely as you’d store passwords, yet many users will inevitably paste them into PHP files committed to repositories.

Verdict

Use if: You’re building personal home automation scripts in PHP, you already have a Nest thermostat and just want programmatic control without navigating Google’s Developer Program bureaucracy, you’re maintaining a legacy PHP-based smart home system that needs Nest integration, or you need features (like detailed energy reports) that the official API doesn’t expose. This library is perfect for cron jobs that adjust temperature based on local weather, personal dashboards showing thermostat history, or HomeKit/SmartThings bridges running on your own infrastructure. Skip if: You’re building anything commercial or distributed to end users—the authentication UX is unacceptable and the legal/support risks of unofficial APIs aren’t worth it. Skip if you need guaranteed long-term stability or SLA-backed uptime; use the official Device Access API instead, despite its limitations. Skip if you’re not working in PHP; the Python alternative (badnest) or Node.js options (homebridge-nest) are better suited to their respective ecosystems and often better maintained. And definitely skip if you’re uncomfortable with the reality that your integration could break tomorrow with no recourse.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/gboudreau-nest-api.svg)](https://starlog.is/api/badge-click/developer-tools/gboudreau-nest-api)