mrkeyoor.com_
Sun 20 Sept 04:54 UTC
PyPIWeb Backendupdated 20 Sept 2026

google-api-python-client review

google-api-python-client 2.199.0 creates Python resource methods from Google Discovery documents bundled with the package. One install can call Drive, Gmail, Calendar, Sheets, YouTube, Admin SDK, and many other discovery-based HTTP APIs through chains ending in `execute()`. Version 2.199.0 mainly refreshes descriptions for a long list of Google services and drops Python 3.7 through 3.9. Google labels the client complete and in maintenance mode, and recommends service-specific Cloud Client Libraries for new Cloud projects.

Verdict

google-api-python-client 2.199.0 left 20 packages and 127 MB in our sandbox despite having only 5 direct dependencies, so it earns its place when one service needs a Discovery client or one process spans several Google APIs. For a supported Google Cloud service, install its dedicated client instead.

We installed it

Lab card: what happened when we installed google-api-python-clientScreenshot of google-api-python-client documentation
Install✓ · 1s20 packages on disk · 127 MB
Importimport apiclient in 0.72s · pure Python · requires Python >=3.10
Known vulns0(pip-audit)

Answers from our run

Does google-api-python-client install cleanly?

Yes. In a fresh container with an empty cache, pip install google-api-python-client finished in 1 seconds, leaving 20 packages and 127 MB on disk. pip-audit reported no known vulnerabilities.

What does google-api-python-client need to run?

Python >=3.10, and nothing compiled: it is pure Python. In our run import apiclient succeeded in 0.72s.

google-api-python-client or google-cloud-storage: which should you use?

google-cloud-storage: Use it for Cloud Storage resources, retries, upload helpers, and a service-specific API surface. google-api-python-client 2.199.0 left 20 packages and 127 MB in our sandbox despite having only 5 direct dependencies, so it earns its place when one service needs a Discovery client or one process spans several Google APIs.

When should you not use google-api-python-client?

For Cloud Storage, BigQuery, Pub/Sub, Firestore, and other services with dedicated Cloud Client Libraries, follow Google's own advice and use the service package for new code.

API stability4/5Version 2.199.0 still uses the established `build()`, resource-chain, `execute()`, `HttpError`, media, pagination, and batch interfaces. Google calls the hand-written library complete and limits future work to important bugs and security fixes. Service methods are generated from changing Discovery documents, however, so request names and schemas can move even when the Python framework stays stable.
Docs4/5The hosted google-api-python-client documentation covers OAuth, service accounts, pagination, media transfers, batches, errors, and thread safety with concrete examples. Its README clearly states the Python 3.10 floor, maintenance status, bundled Discovery behavior, and preference for Cloud Client Libraries. Exact method parameters still live in each service's API reference, while runtime generation limits useful Python signatures and editor feedback.
Maintenance3/5Google officially supports the unarchived repository, which was pushed on August 26, 2026. GitHub shows 8,914 stars and 45 open issues and pull requests. Version 2.199.0 shipped on August 20 with many generated service-description updates and the Python 3.7 to 3.9 removal. The release cadence is active, but the README's maintenance-mode statement rules out new client features.
Ecosystem5/5The supplied registry count is about 41 million weekly downloads, and GitHub reports 8,914 stars. One package reaches many Google Workspace, consumer, advertising, and Cloud APIs, and it accepts credentials from `google-auth`. Years of Google quickstarts use `build()` and `execute()`. That reach is broad, though newer Cloud libraries offer better typing and service-specific behavior.

Use it if

  • You need a Google Workspace or consumer API that has no dedicated modern Python client.
  • One backend calls several discovery-based Google APIs and can reuse the same authentication, pagination, media, and batch conventions.
  • The job requires resumable uploads, chunked downloads, or HTTP batches provided by the shared client.
  • Bundled Discovery documents are preferable to downloading an API description during startup.
Skip it if

Setup reality

Our fresh Python 3.12 install of google-api-python-client 2.199.0 completed in 1 second. It produced an environment of 20 packages and 127 MB, and pip-audit found 0 known vulnerabilities. The pure-Python package lists 5 direct dependencies, requires Python 3.10+, has no py.typed marker, and uses Apache 2.0. Importing the compatibility name apiclient succeeded in 0.72 seconds.

Authentication usually takes longer than installation. Public endpoints may accept an API key. User data needs an OAuth client, consent, exact scopes, and protected refresh credentials. Server code can use Application Default Credentials or a service account, but that account sees no user's Drive files until they are shared. Workspace domain-wide delegation requires administrator approval for the scopes and explicit user impersonation. A disabled API can return 403 even with valid credentials.

build() in version 2.199.0 constructs resource methods from Discovery descriptions shipped in the distribution instead of fetching them at startup. That removes one network dependency and helps explain the 127 MB environment. Description updates make up much of the frequent release stream, so pin the client when an unexpected service schema change would be risky. Use a fields mask because responses are ordinary nested dictionaries and omitted-field mistakes otherwise surface at runtime.

Every execute() call blocks, and httplib2.Http is not thread-safe. Create an authorized transport for each worker rather than sharing one across a pool. Batch completion does not imply that all subrequests succeeded; inspect each callback. Resumable uploads require repeated next_chunk() calls until a final response arrives. When Google returns 403, read the structured reason before retrying because disabled APIs, exhausted quota, and missing scopes can use the same status.

Patterns

Use an API key for public data build-api-key-client

from googleapiclient.discovery import build

youtube = build("youtube", "v3", developerKey=API_KEY)
result = youtube.search().list(
    part="snippet", q="python", maxResults=5
).execute()

An API key identifies the Cloud project and quota consumer. It does not authorize access to private Google user data.

Build a client from default credentials use-application-default-credentials

import google.auth
from googleapiclient.discovery import build

credentials, project_id = google.auth.default(
    scopes=["https://www.googleapis.com/auth/drive.readonly"]
)
drive = build("drive", "v3", credentials=credentials)

Application Default Credentials must be available through a supported source, and the selected API must be enabled in the credential project.

Read credentials from a service account use-service-account

from google.oauth2 import service_account
from googleapiclient.discovery import build

credentials = service_account.Credentials.from_service_account_file(
    "service-account.json",
    scopes=["https://www.googleapis.com/auth/drive.readonly"],
)
drive = build("drive", "v3", credentials=credentials)

A service account has its own identity. Share Drive content with that address or configure approved Workspace delegation.

Act as a Workspace user impersonate-workspace-user

delegated = credentials.with_subject("user@example.com")
admin = build("admin", "directory_v1", credentials=delegated)
users = admin.users().list(customer="my_customer").execute()

An administrator must authorize the service account and every requested OAuth scope before `with_subject()` can access domain data.

Run local user consent run-installed-app-oauth

from google_auth_oauthlib.flow import InstalledAppFlow

flow = InstalledAppFlow.from_client_secrets_file(
    "client_secret.json", SCOPES
)
credentials = flow.run_local_server(port=0)
print(credentials.to_json())

`google-auth-oauthlib` is installed separately. Protect the refresh credential and repeat consent when the scope list changes.

Walk every result page paginate-list-method

resource = drive.files()
request = resource.list(
    pageSize=100, fields="nextPageToken,files(id,name)"
)
while request is not None:
    response = request.execute()
    for item in response.get("files", []):
        print(item["id"], item["name"])
    request = resource.list_next(request, response)

A narrow `fields` mask must include `nextPageToken`; without it, `list_next()` cannot find the following page.

Ask only for required fields request-partial-response

response = drive.files().list(
    q="trashed = false",
    fields="nextPageToken,files(id,name,mimeType)",
).execute()

Fields that are absent from the mask are absent from the returned dictionary, so callers must not assume a full resource body.

Inspect the reason inside an HTTP error classify-http-error

import json
from googleapiclient.errors import HttpError

try:
    request.execute()
except HttpError as error:
    payload = json.loads(error.content.decode("utf-8"))
    reason = payload.get("error", {}).get("errors", [{}])[0].get("reason")
    print(error.resp.status, reason)
    raise

A 403 can mean missing scope, disabled API, quota policy, or another cause. Branch on the structured reason before deciding to retry.

Send a resumable upload upload-resumable-media

from googleapiclient.http import MediaFileUpload

media = MediaFileUpload("report.pdf", mimetype="application/pdf", resumable=True)
request = drive.files().create(
    body={"name": "report.pdf"}, media_body=media, fields="id"
)
response = None
while response is None:
    status, response = request.next_chunk()

`next_chunk()` may return progress without a resource. Continue until the final response is non-null and preserve enough state for interrupted jobs.

Download media incrementally download-media-in-chunks

import io
from googleapiclient.http import MediaIoBaseDownload

buffer = io.BytesIO()
request = drive.files().get_media(fileId=file_id)
downloader = MediaIoBaseDownload(buffer, request)
done = False
while not done:
    status, done = downloader.next_chunk()

Stored binary files use `get_media()`. Native Google Docs files require `export_media()` plus an export MIME type.

Collect independent calls in one batch execute-batch-request

def finished(request_id, response, exception):
    if exception:
        failures[request_id] = exception
    else:
        results[request_id] = response

batch = drive.new_batch_http_request(callback=finished)
for file_id in file_ids:
    batch.add(drive.files().get(fileId=file_id), request_id=file_id)
batch.execute()

The outer HTTP batch can complete while individual requests fail. Record the exception passed to every callback.

Give each thread its own transport isolate-thread-transports

import httplib2
import google_auth_httplib2

def authorized_http():
    return google_auth_httplib2.AuthorizedHttp(
        credentials, http=httplib2.Http()
    )

def fetch(file_id):
    return drive.files().get(fileId=file_id).execute(
        http=authorized_http()
    )

`httplib2.Http` is not thread-safe. Build a distinct authorized HTTP object for every concurrent worker.

Alternatives

PackageRegistryPick it when
google-cloud-storagePyPIUse it for Cloud Storage resources, retries, upload helpers, and a service-specific API surface.
google-cloud-bigqueryPyPIUse it when BigQuery is the only service and typed jobs, tables, rows, and query helpers matter.
google-api-corePyPIUse it as shared infrastructure when building around generated Google Cloud clients rather than Discovery resources.

More web backend guides

urllib3 · requests · ws · anyio · httpx · undici · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.