Skip to main content

Gmail

This page contains the setup guide and reference information for the Gmail source connector.

Gmail is the email service provided by Google. The Gmail source connector replicates messages, drafts, threads, labels, and the authenticated user's profile from Gmail's REST API.

Prerequisites​

  • A Google account with access to the mailbox you want to replicate.
  • A Gmail API scope that allows reading mail. Airbyte Cloud's OAuth flow requests https://www.googleapis.com/auth/gmail.modify, which includes read access. An OAuth client you manage yourself can grant the narrower https://www.googleapis.com/auth/gmail.readonly scope. In either case, the connector only issues read requests.
  • For Airbyte Open Source: a Google Cloud project with the Gmail API enabled, plus an OAuth 2.0 client and refresh token.

Setup guide​

Step 1: Set up authentication​

The Gmail source connector offers two authentication methods: OAuth and Service Account Key. Use OAuth. Service Account Key authentication can't currently read a mailbox.

In Airbyte Cloud, sign in with the Google account whose mailbox you want to replicate. Airbyte Cloud handles the OAuth flow for you — you only need to authorize Airbyte through the standard Google consent screen when configuring the source. The consent screen requests https://www.googleapis.com/auth/gmail.modify, so it asks you to let Airbyte read, compose, and send mail. The connector only issues read requests.

Sources that were authorized before connector version 0.1.11 keep the scope Google granted at consent time. You don't need to re-authenticate them.

OAuth for Airbyte Open Source​

To authenticate with OAuth in Airbyte Open Source, create your own OAuth client in your Google Cloud project and complete the authorization code flow yourself to obtain a refresh token. You will need the resulting Client ID, Client Secret, and Refresh Token to configure the connector.

  1. In the Google Cloud console, enable the Gmail API for your project.

  2. Configure your OAuth consent screen and add a Gmail scope. Which scope you add depends on how you complete the flow:

    • If you obtain the refresh token yourself, add https://www.googleapis.com/auth/gmail.readonly.
    • If you register your OAuth client with your Airbyte instance and click Authenticate your account, add https://www.googleapis.com/auth/gmail.modify. Airbyte builds that consent URL from the connector, which requests gmail.modify, and the scope has to be configured on your consent screen.

    See Choose Gmail API scopes.

  3. Follow Google's web server OAuth 2.0 guide to create a Web application OAuth client and exchange the authorization code for a refresh token.

note

If you configured this source before version 0.1.1, Client ID, Client Secret, and Refresh Token were top-level fields. The connector moves them into the nested Authentication object automatically the first time it runs on a newer version, as long as all three values are present. You don't need to re-enter them. Sources that already use the nested OAuth or Service Account Key configuration aren't changed.

Service Account Key for Airbyte Open Source​

warning

Service Account Key authentication can't currently read a mailbox. To read a user's mailbox, Google requires the token request to name the user to impersonate in the sub claim, and only applies domain-wide delegation when that claim is set. The connector doesn't set sub and has no field for the user to impersonate, so Google issues a token for the service account itself. A service account has no Gmail mailbox, so the connection test and syncs fail with Precondition check failed, whether or not domain-wide delegation is configured. Use OAuth instead.

Step 2: Set up the Gmail connector in Airbyte​

  1. Log into your Airbyte instance, click Sources, and click + New source.
  2. Select Gmail from the source type dropdown.
  3. Choose your authentication method:
    • Authenticate via Google (OAuth) — Click Authenticate your account and complete the Google sign-in flow. Airbyte Cloud users authenticate against Airbyte's pre-registered OAuth app. Airbyte Open Source users provide their own Client ID, Client Secret, and Refresh Token.
    • Service Account Key Authentication — Not currently usable. The connector authenticates as the service account itself, which has no mailbox. Use OAuth instead.
  4. (Optional) Set Start date in YYYY-MM-DDTHH:MM:SSZ format. Only messages, drafts, and threads received on or after this date are replicated. If you leave it blank, the connector replicates the full mailbox history.
  5. (Optional) Toggle Include Spam & Trash to include drafts and messages from the Spam and Trash folders. Defaults to off.
  6. (Optional) Adjust Number of concurrent workers (between 2 and 10, default 5) to control how many requests the connector issues in parallel. Lower this value if you see frequent rate-limit errors.
  7. Click Set up source to test the connection and save the configuration. The connection test reads the authenticated user's Gmail profile.

Supported sync modes​

The Gmail source connector supports the following sync modes:

Sync modeSupported
Full Refresh | OverwriteYes
Full Refresh | AppendYes
Incremental | AppendYes
Incremental | Append + DedupedYes

Only the messages_details stream supports incremental sync. All other streams run in full refresh mode on every sync.

Streams​

StreamPrimary KeySync ModeDescription
profileemailAddressFull RefreshThe authenticated user's Gmail profile, including email address and history ID.
draftsidFull RefreshStub records (id, message.id, message.threadId) returned by users.drafts.list.
labelsidFull RefreshAll Gmail labels, including system labels (e.g. INBOX, SENT) and user-created labels.
labels_detailsidFull RefreshPer-label metadata such as message and thread counts. Substream of labels.
messagesidFull RefreshStub records (id, threadId) returned by users.messages.list.
messages_detailsidIncremental on internalDateFull message payloads, headers, snippet, and labels.
threadsidFull RefreshStub records (id, snippet, historyId) returned by users.threads.list.
threads_detailsidFull RefreshPer-thread details and the messages in each thread. Substream of threads.

The messages_details cursor is the message's internalDate field — the Unix epoch in milliseconds when Gmail received the message. The other streams have no record-level cursor field, so they run as full refresh.

On incremental syncs, messages_details lists messages received since the previous sync, with a one-hour lookback, and fetches details only for those returned IDs. This re-emits messages received during the hour before the previous sync, so append-only destinations can receive duplicates; Append + Deduped avoids them. Gmail's after: filter uses received time rather than modification time, so incremental syncs don't pick up changes to older messages, such as new labels or read state. They also never fetch a message that enters the mailbox later with an older received time, such as mail moved out of Spam or Trash while Include Spam & Trash is off, or mail imported from another account. To keep labels and read state current for older messages, run a full refresh periodically. If you leave Start date blank, the initial lower bound is 2004-04-01, the date Gmail launched.

The first incremental sync of messages_details reads every message since Start date. This includes the first sync after you upgrade to version 0.3.0, because state saved by earlier versions doesn't bound the list request. The connector lists messages in 30-day windows and saves state after each window, so if the sync fails, the next sync resumes from the last completed window.

When Start date is set, the connector applies the Gmail after:<epoch_seconds> search operator to the messages (including the internal list used by messages_details), drafts, and threads list requests so the API skips records older than that date.

Performance considerations​

The Gmail API enforces a per-project and a per-user rate limit, measured in quota units. The limits and the cost of each call depend on when the Google Cloud project behind your credentials started using the Gmail API:

QuotaEarlier projects (used the API November 2025 to April 2026)Projects created on or after May 1, 2026
Per-project limit (rateLimitExceeded)1,200,000 units per minute1,200,000 units per minute
Per-user limit (userRateLimitExceeded)15,000 units per minute per user6,000 units per minute per user
threads.get10 units120 units
messages.get5 units60 units
threads.list10 units10 units
messages.list5 units5 units

On projects created on or after May 1, 2026, drafts.list costs 5 units, and labels and profile calls cost 1 unit. The get costs for these projects apply to full-format reads, which is what the connector requests. The messages_details and threads_details substreams issue one get call per parent record, so high-volume mailboxes consume quota quickly.

The connector paces its requests to stay under the per-user limit, based on the authentication method:

  • OAuth: the connector assumes the earlier quota, because Airbyte Cloud's OAuth app belongs to a project that kept it. If you use your own OAuth client on a project created on or after May 1, 2026, the connector can send more requests than your quota allows, and relies on Gmail's rate-limit responses instead.
  • Service Account Key: the connector assumes the newer quota, since the service account belongs to your own project. Service Account Key authentication can't currently read a mailbox, so this has no effect yet.

The per-project limit is shared with every other user of the project, so the connector can't track it and relies on Gmail's rate-limit responses for it.

The connector retries 429 Too Many Requests and 403 quota-saturation errors. It decides how long to wait before each retry as follows:

  1. If the response has a Retry-After header, it waits that long.
  2. Otherwise, if the error message contains a Retry after <timestamp> time, it waits until that time, up to 30 minutes.
  3. Otherwise, it uses exponential backoff.

A request is retried up to 10 times, and the connector stops retrying after about 10 minutes. A wait taken from the error message can run past that limit. In that case, the connector retries once after the wait and fails the request if that retry also fails. After a 429, every request also waits up to a minute for the current quota window to clear. If you see frequent rate-limit warnings in sync logs, lower the Number of concurrent workers setting.

Limitations & troubleshooting​

  • messages and threads are stub-only. The Gmail API's users.messages.list and users.threads.list endpoints return only {id, threadId} (or {id, snippet, historyId}) per record. To replicate the full message body, headers, or labels, sync messages_details or threads_details. You don't need to also select messages or threads, and selecting messages adds a full mailbox list on every sync.
  • Service account keys can't read a mailbox. The connector doesn't set the sub claim that Google requires for a service account to impersonate a user, so the token belongs to the service account, which has no mailbox. Domain-wide delegation doesn't change this. Use OAuth instead.
  • Precondition check failed. The authenticated account has no Gmail mailbox. Either you used Service Account Key authentication, or you authorized a Google Workspace user who doesn't have Gmail enabled. Authenticate with OAuth as the user whose mailbox you want to sync.
  • The Gmail API isn't enabled. On Airbyte Open Source with your own OAuth client, the connector fails with a configuration error until you enable the Gmail API in the Google Cloud project that owns the client.
  • The authorized account lacks the required scope. If Gmail returns insufficientPermissions, re-authenticate and grant https://www.googleapis.com/auth/gmail.readonly (a refresh token you obtained yourself) or https://www.googleapis.com/auth/gmail.modify (the Authenticate your account flow).
  • Your Workspace administrator has disabled Gmail apps. If Gmail returns domainPolicy, ask your Google Workspace administrator to allow Gmail API access for the app, then retry.
  • The Cloud consent screen asks for more access than the connector uses. https://www.googleapis.com/auth/gmail.modify lets an app read, compose, and send mail, change labels, and trash messages. This connector only issues GET requests. To grant the narrower https://www.googleapis.com/auth/gmail.readonly scope instead, use your own OAuth client on a self-managed Airbyte instance.

Configuration​

InputTypeDescriptionDefault Value
credentialsobjectAuthentication. Credentials for connecting to the Gmail API.
credentials.client_idstringClient ID. Enter your Google application's Client ID. See Google's documentation for more information.
credentials.client_secretstringClient Secret. Enter your Google application's Client Secret. See Google's documentation for more information.
credentials.client_refresh_tokenstringRefresh Token. Enter your Google application's refresh token. See Google's documentation for more information.
credentials.service_account_infostringService Account Information. The JSON key of the service account to use for authorization.
include_spam_and_trashbooleanInclude Spam & Trash. Include drafts/messages from SPAM and TRASH in the results. Defaults to false.false
num_workersintegerNumber of concurrent workers. Higher values result in faster syncs but may trigger rate limiting on lower-tier Gmail API quotas. Reduce this value if you see frequent rate-limit errors in sync logs.5
start_datestringUTC date and time in the format YYYY-MM-DDTHH:MM:SSZ. Only messages, threads, and drafts received on or after this date will be replicated. If unset, the full history is replicated.

IP allow list​

If you use Airbyte Cloud and your organization restricts access to specific IPs, add the Airbyte Cloud IP addresses to your allow list.

Reference​

Config fields reference

Field
Type
Property name
object
credentials
boolean
include_spam_and_trash
integer
num_workers
string
start_date

Changelog​

Expand to review
VersionDatePull RequestSubject
1.0.12026-10-2890147Request 500 items per page from Gmail list endpoints
1.0.02026-10-2789502Add profile primary key and type count and size fields as integers
0.3.02026-10-2789756Bound incremental messages_details reads to the previous sync with a one-hour lookback
0.2.02026-10-2789703Pace requests to the Gmail per-user quota
0.1.242026-10-2789912Update dependencies
0.1.232026-10-2088896Declare nested message parts and honor Gmail's rate-limit retry time
0.1.222026-10-2089234Update dependencies
0.1.212026-10-1388403Check connections via the profile endpoint and retry rate-limited requests
0.1.202026-10-1388635Update dependencies
0.1.192026-10-0687854Update dependencies
0.1.182026-09-2987179Update dependencies
0.1.172026-09-2286632Update dependencies
0.1.162026-09-1586066Update dependencies
0.1.152026-09-1185800Fix config migration copying empty or incomplete legacy OAuth fields into nested credentials
0.1.142026-09-0885497Update dependencies
0.1.132026-08-1884554Update dependencies
0.1.122026-08-1183951Update dependencies
0.1.112026-08-0483308Request the gmail.modify scope in Airbyte Cloud's OAuth flow
0.1.102026-08-0483463Update dependencies
0.1.92026-07-2882922Update dependencies
0.1.82026-07-2182425Update dependencies
0.1.72026-07-1481816Update dependencies
0.1.62026-06-3081079Update dependencies
0.1.52026-06-2380468Update dependencies
0.1.42026-06-1679869Update dependencies
0.1.32026-06-0979310Update dependencies
0.1.22026-06-0278732Update dependencies
0.1.12026-05-0476065Add OAuth and service account authentication
0.1.02026-04-2976431Add incremental messages_details sync, start_date filtering and rate-limit handling
0.0.522026-04-2877264Update dependencies
0.0.512026-04-2176616Update dependencies
0.0.502026-03-2475387Update dependencies
0.0.492026-03-1074532Update dependencies
0.0.482026-03-0374205Update dependencies
0.0.472026-02-1173300Revert OAuth authentication support
0.0.462026-02-1173273Add OAuth authentication support (reverted in 0.0.47)
0.0.452026-02-1072593Update dependencies
0.0.442026-01-2071967Update dependencies
0.0.432026-01-1471388Update dependencies
0.0.422025-12-1870726Update dependencies
0.0.412025-11-2569871Update dependencies
0.0.402025-11-1869412Update dependencies
0.0.392025-10-2969004Update dependencies
0.0.382025-10-2168299Update dependencies
0.0.372025-10-1467999Update dependencies
0.0.362025-10-0767258Update dependencies
0.0.352025-09-3066299Update dependencies
0.0.342025-09-0966063Update dependencies
0.0.332025-08-2365371Update dependencies
0.0.322025-08-0964626Update dependencies
0.0.312025-08-0264194Update dependencies
0.0.302025-07-2663861Update dependencies
0.0.292025-07-1963463Update dependencies
0.0.282025-07-1263123Update dependencies
0.0.272025-07-0562624Update dependencies
0.0.262025-06-2862169Update dependencies
0.0.252025-06-2161834Update dependencies
0.0.242025-06-1461134Update dependencies
0.0.232025-05-2460608Update dependencies
0.0.222025-05-1059895Update dependencies
0.0.212025-05-0359276Update dependencies
0.0.202025-04-2658813Update dependencies
0.0.192025-04-1958184Update dependencies
0.0.182025-04-1257732Update dependencies
0.0.172025-04-0557214Update dependencies
0.0.162025-03-2955947Update dependencies
0.0.152025-03-0855265Update dependencies
0.0.142025-03-0154937Update dependencies
0.0.132025-02-2254417Update dependencies
0.0.122025-02-1553369Update dependencies
0.0.112025-02-0152831Update dependencies
0.0.102025-01-2552329Update dependencies
0.0.92025-01-1851700Update dependencies
0.0.82025-01-1151110Update dependencies
0.0.72024-12-2850536Update dependencies
0.0.62024-12-2150008Update dependencies
0.0.52024-12-1449474Update dependencies
0.0.42024-12-1249185Update dependencies
0.0.32024-10-2947852Update dependencies
0.0.22024-10-2847570Update dependencies
0.0.12024-10-09Initial release by @topefolorunso via Connector Builder