# Read a Google Sheet in Python

The library-first answer is gspread, and it works — but it drags a Google Cloud project along with it. Here are all three routes, and how to choose.

*Last updated: 2026-07-13 · Source: <https://pastesheet.com/guides/read-google-sheet-in-python>*

## Key facts

- Google's API requires a **Google Cloud project plus OAuth credentials or a service account** before it will return a single row. ([source](https://developers.google.com/workspace/sheets/api/guides/authorizing))
- That applies to `gspread` too — it is a client for Google's API, so it inherits the Cloud project and the service-account JSON even when all you want is a read. ([source](https://cloud.google.com/iam/docs/service-account-overview))
- The Google Sheets API allows **300 read requests per minute per project** and **60 per minute per user**. Past that it returns `429 RESOURCE_EXHAUSTED`. ([source](https://developers.google.com/workspace/sheets/api/limits))
- A cached endpoint reads the sheet **once per TTL**, not once per request — so 10,000 visitors become one upstream read, and Google's quota stops being your problem.

## How do you read a Google Sheet in Python?

There are three routes. Use `gspread` if you need to write back or read a private sheet. Use the official `google-api-python-client` if you need low-level control. If you only need to *read* a shared sheet, fetch it over plain HTTP — no library, no credentials.

Most scripts fall into that third case and reach for the first out of habit, which is how a five-line read turns into a Cloud project.

## The simplest version: plain HTTP

Connect the sheet to PasteSheet once, then read typed JSON with `requests`. Filtering, sorting, and pagination are query parameters:

```bash
import requests

res = requests.get(
    "https://pastesheet.com/api/your-endpoint-id",
    params={"status": "active", "sort": "-created", "limit": 100},
).json()

for row in res["data"]:
    print(row["name"], row["email"])

print(res["total"], "rows total")
```

## Which route?

|  | gspread | Official API | HTTP endpoint |
| --- | --- | --- | --- |
| Google Cloud project | Required | Required | Not required |
| Credentials to manage | Service account JSON | OAuth / service account | None |
| Can write | Yes | Yes | No |
| Typed values | Partly | No — raw cells | Yes |
| Filter & sort server-side | No | No | Yes |
| Subject to Google quota | Yes | Yes | Cached — see below |

## The quota gotcha

If your script runs often, or runs per-request in a web app, you will meet Google's ceiling: **300 reads per minute per project, 60 per minute per user**, then a `429` ([published limits](https://developers.google.com/workspace/sheets/api/limits)). A cached endpoint reads the sheet once per window regardless of how many times your code asks.

## What it costs

**MCP is included on the Free plan.** Connect any **public** endpoint over MCP with no Google Cloud project and no credit card. Private endpoints and the account-wide workspace server need a paid plan (from **Starter ($9/mo)**) for the keys and OAuth they authenticate with.

Pro adds full-text search and aggregation (`count`, `sum`, `avg`, `group_by`) that your AI agent can call through `query_rows`.

**Free — $0/month.** For side projects and trying things out.

- Endpoints: 3
- Requests: 2,000 / month
- Rows per endpoint: 500
- Tabs per endpoint: 1
- Rate limit: 60 / minute

## Frequently asked questions

### What is the easiest way to read a Google Sheet in Python?

If the sheet is shared publicly, a plain HTTP GET against a JSON endpoint — no library and no credentials. gspread is easiest if you also need to write or read a private sheet.

### Do I need gspread?

Only if you need write access or private-sheet reads. For read-only access to a shared sheet, gspread adds a Google Cloud project and a service account you would not otherwise need.

### How do I avoid hitting Google's rate limit from a script?

Cache the results. Google allows 60 reads per minute per user, which a loop or a per-request web handler will exhaust quickly. Reading through a cached endpoint makes your call volume irrelevant to Google.

### Can I write back to the sheet this way?

Not through PasteSheet — it is read-only by design. Use gspread or the official API for writes, and keep the read path cached and fast.

## Sources

- [Authorize requests — Google Sheets API](https://developers.google.com/workspace/sheets/api/guides/authorizing) — Google
- [Usage limits — Google Sheets API](https://developers.google.com/workspace/sheets/api/limits) — Google
- [Service accounts overview](https://cloud.google.com/iam/docs/service-account-overview) — Google Cloud

## Related guides

- [Google Sheets MCP Server in Python](https://pastesheet.com/guides/google-sheets-mcp-python) — Build or connect a Google Sheets MCP server from Python. Compare the DIY route against a hosted endpoint, with working client code for both paths.
- [How to Read a Google Sheet in Laravel](https://pastesheet.com/guides/read-google-sheet-in-laravel) — Pull Google Sheet rows into Laravel as typed JSON with Http::get and a cache. No Google client library, no service account JSON, no Cloud project.
- [How to Read a Google Sheet in React](https://pastesheet.com/guides/read-google-sheet-in-react) — Fetch Google Sheet rows into a React app as JSON. Why you cannot safely call Google's API from the browser, and what to do instead. With working code.
- [Fix Google Sheets API Quota Exceeded (429)](https://pastesheet.com/guides/google-sheets-api-quota-exceeded) — Seeing RESOURCE_EXHAUSTED or a 429 from the Google Sheets API? Here is the per-minute quota, why you hit it, and how caching removes it for read-heavy apps.

---

[PasteSheet](https://pastesheet.com) turns any Google Sheet into a live REST API and MCP server for AI agents — no backend, no code. Canonical HTML version of this page: <https://pastesheet.com/guides/read-google-sheet-in-python>
