Skip to main content

gclientid

Create Google OAuth desktop client IDs locally, without requiring gcloud.

CLI

Install gclientid, enable Allow remote debugging in chrome://inspect/#remote-debugging, and run:

pip install gclientid
gclientid

Chrome asks you to approve the debugging connection. gclientid opens a separate tab, creates a dedicated project with a unique gclientids-* ID, configures and publishes its unverified Gmail OAuth application, creates a Desktop client, and authorizes the selected Gmail account.

Credentials are written with mode 0600 under ~/.config/gclientid/<project-id>/:

oauth-client.json
oauth-token.json

The main options are:

gclientid --project my-unique-project-id
gclientid --account j@example.com
gclientid --accept-terms
gclientid --cdp-chrome
gclientid --output ./credentials

Run gclientid --help for all options. Existing credential files are never overwritten.

Python API

gclientid uses an existing signed-in fastcdp Chrome session. Enable Allow remote debugging in chrome://inspect/#remote-debugging, then create a globally unique project ID, provision its Gmail Desktop OAuth client, and authorize the Gmail account:

from gclientid import authorize_gmail, connect_browser, create_gmail_client, create_project

cdp, page = await connect_browser()
project_id = 'gclientids-your-unique-suffix'

await create_project(page, project_id, name='gclientids')
await create_gmail_client(page, project_id, 'oauth-client.json')
await authorize_gmail(cdp, 'oauth-client.json', 'oauth-token.json')

connect_browser() uses the normal Chrome profile by default. Chrome gives you 60 seconds to approve the debugging connection. The function opens a new tab instead of navigating the currently focused tab. To use the separate CDP Chrome profile on port 9223 instead:

cdp, page = await connect_browser(default_browser=False)

create_gmail_client enables the Gmail API, configures an External OAuth application, adds the full Gmail scope, publishes the unverified application, creates a Desktop client, and writes Google's installed-app client JSON. It selects an email offered by the signed-in Google account for the support and contact fields. It does not require an email or username argument.

On a new Google Auth Platform application, create_gmail_client pauses at Google's API Services terms screen. Complete that visible screen in Chrome and the function continues. Pass accept_terms=True to accept and submit that screen automatically:

await create_gmail_client(page, project_id, 'oauth-client.json', accept_terms=True)

authorize_gmail opens Google's account and consent screens in a new Chrome tab. It selects the account automatically when Google offers one existing account, then approves the requested Gmail access. When Google offers multiple existing accounts, select one by display name or email substring:

await authorize_gmail(cdp, 'oauth-client.json', 'oauth-token.json', account='j@example.com')

The function uses a PKCE loopback flow and writes the access token, refresh token, granted scope, client ID, and creation time to oauth-token.json.

Both JSON files are created with mode 0600. create_gmail_client refuses to overwrite an existing client file because Google only exposes the Desktop client secret at creation time. authorize_gmail replaces the token file when authorization succeeds. Keep both files out of git.

Project deletion is also available. Google keeps a deleted project recoverable for 30 days:

from gclientid import delete_project

await delete_project(page, project_id)

See the privacy policy for how Google user data is handled.

Personal OAuth applications

The intended setup is one Google Cloud project and Desktop OAuth client per developer. Configure its audience as External, publish it In production, and leave it unverified. Google may say that the app "requires verification", but personal-use applications can still authorize up to 100 distinct users. Users see an unverified-app warning during initial authorization; verification is only needed to remove that warning or exceed the lifetime user cap.

Do not leave a continuously running application in Testing. Testing requires an explicit test-user email list, and authorizations requesting Gmail access expire after seven days. An unverified app that is In production needs neither the allowlist nor seven-day reauthorization.

The unrestricted Gmail scope is https://mail.google.com/. It is a restricted scope and allows reading, composing, sending, and permanently deleting mail. The application must request this scope during authorization even when it is already listed on the Google Auth Platform Data Access page.

Google currently requires a Desktop client's client_secret during the token exchange, including when PKCE is used. The secret is shown only when the client is created, so capture or download the client JSON immediately. Desktop software cannot keep this value confidential, but it must still be kept out of git along with user access and refresh tokens.

Development

pip install -e .[dev]

Versioning

Version lives in gclientid/__init__.py as __version__. Bump it with:

ship-bump --part 2   # patch
ship-bump --part 1   # minor
ship-bump --part 0   # major

Release

  1. Ensure your GitHub issues are labeled (bug, enhancement, breaking).
  2. Run:
ship-release

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gclientid-0.1.1.tar.gz (15.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gclientid-0.1.1-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

Details for the file gclientid-0.1.1.tar.gz.

File metadata

  • Download URL: gclientid-0.1.1.tar.gz
  • Upload date:
  • Size: 15.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for gclientid-0.1.1.tar.gz
Algorithm Hash digest
SHA256 bae0e36afcc06602a853735b8c597b826648a6fa789e270b9820ad806e312897
MD5 ae10e05227be0ce5cac958716e2d9bab
BLAKE2b-256 5be0a40c992e6eb7956b1b41329a4515f6168526f00ee067e27ec57f47eef9e5

See more details on using hashes here.

File details

Details for the file gclientid-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: gclientid-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 14.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.15

File hashes

Hashes for gclientid-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a9af0c7aa6abfdddf7b0dad88847f0ac5f0741905a3e3d2b446129bbaca6fa97
MD5 d312a069c282b01c536283004a147469
BLAKE2b-256 7469895e69668853164ad9b2e880fe77f1045deb70ce020c6f725a3f503d9bd1

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

This release

0.1.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page