TechEarl

Reading a Google Sheet in PHP: CSV vs the API

Two ways to read a Google Sheet from PHP: publish-to-web CSV (trivial, but public to anyone with the URL) or the Sheets API with a service account (private, scoped). The security trade-off, shown.

Ishan Karunaratne⏱️ 5 min readUpdated
Share thisCopied
Reading a Google Sheet from PHP two ways: a public publish-to-web CSV versus the authenticated Sheets API with a service account

There are two ways to read a Google Sheet from PHP, and they sit at opposite ends of a security trade-off. You can publish the sheet to the web and fetch it as CSV, which is trivial to set up but makes the data readable by anyone who has (or guesses, or is shown) the URL. Or you can read it through the Sheets API with a service account, which is a little more setup but keeps the sheet private, scoped, and revocable. The code difference is small; the exposure difference is the whole decision.

The CSV way: publish to web

In the sheet, File → Share → Publish to web → CSV. Google hands you a URL that returns the tab as CSV, and PHP reads it in a few lines:

php
$url  = 'https://docs.google.com/spreadsheets/d/e/<published-id>/pub?gid=0&single=true&output=csv';
$rows = array_map( 'str_getcsv', file( $url, FILE_IGNORE_NEW_LINES ) );
$head = array_shift( $rows );
foreach ( $rows as $row ) {
	$data = array_combine( $head, $row );
	// $data['post_id'], $data['new_currency'], ...
}

No credentials, no tokens, no libraries. That is the appeal. The cost is in the second word of "publish to web": the sheet is now public. Anyone with that URL reads the data, the URL can be shared or leaked, and a published sheet is the kind of thing that turns up in logs, referrers, and the occasional search index. It is the right tool for data that is genuinely public anyway (a price list you'd put on the site regardless). It is the wrong tool for anything you would not paste into a public Gist.

The API way: a service account

The Sheets API reads the same data, but the sheet stays private. You share it with a service account (read-only), and your server authenticates as that account. The full token-minting and reading code is in bulk-updating WordPress fields from a Google Sheet; the short version is a signed JWT exchanged for an access token, then a GET with a Bearer header.

The security difference is not theoretical, and you can see it. The same private sheet, hit without a token, is refused; hit with the service account's token, it returns the rows:

Two curl requests to the Sheets API for the same private sheet: the first with no Authorization header returns HTTP 403 PERMISSION_DENIED, the second with a service-account Bearer token returns HTTP 200 and the sheet rows
The same private sheet over the API: 403 with no token, 200 with the service account's token. A published CSV would return 200 to anyone.

That 403 is the point. With the API, the sheet is closed by default and opens only for an identity you control and can revoke. With a published CSV, the equivalent request from anyone returns 200. Same data, opposite default.

Which to use

Publish-to-web CSVSheets API + service account
Setupone menu clickservice account, key, share
Credentialsnonea JSON key on the server
Who can read the dataanyone with the URLonly the authenticated account
Revoke accessunpublish (and hope no copies)delete the key or unshare
Right forgenuinely public dataanything private

Reach for CSV only when the data is public anyway and you want the least possible machinery. For anything that lives behind a login, anything with personal data, or anything a competitor would enjoy reading, the service account is not optional, it is the baseline. The few minutes of setup buys you a private, auditable, revocable connection instead of a public URL you can never fully un-share.

Once you can read the sheet, applying it to WordPress is the pull/batch pattern; wrap the write in the safe batch updater's dry-run and change-only rails so a bad row is recoverable.

Sources

Authoritative references this article was fact-checked against.

TagsWordPressGoogle SheetsPHPSecurityService Account

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts