---
title: "Search Console API authentication with OAuth"
description: "Set up read-only Google OAuth access, confirm property permissions, and diagnose expired tokens or redirect errors."
canonical_url: "https://gscdump.com/learn-google-search-console/api/authentication"
last_updated: "2026-09-11"
---

To read a property's Search Console data, your application needs a Google OAuth access token for an account that can access that property.

Two permissions must line up: the account's Search Console access and the access granted to your application. Requesting a scope does not add the account to a property.

An ordinary Google API key won't authorize private Search Console data. A gscdump API key is also a different credential, used with gscdump rather than Google's API. Google documents the required protocol and scopes in [Authorize Requests](https://developers.google.com/webmaster-tools/v1/how-tos/authorizing).

## Start with read-only access

For reporting, request:

```text
https://www.googleapis.com/auth/webmasters.readonly
```

The broader `https://www.googleapis.com/auth/webmasters` scope includes write access. Choose it only when your application needs the corresponding operations.

This guide follows the common case of a server-side web application. An installed local application uses a different OAuth client type and flow. Google's [OAuth overview](https://developers.google.com/identity/protocols/oauth2) links those alternatives.

## Configure the web application

In your Google Cloud project, enable the Search Console API, configure the OAuth consent settings, and create a web application OAuth client.

Register the exact callback URL your server handles, for example `https://app.example.com/oauth/google/callback`. Scheme, host, port, path, and trailing slash matter. A different local development callback needs its own registered URI.

Use Google's client library for your language and follow its [web server OAuth guide](https://developers.google.com/identity/protocols/oauth2/web-server). Your application still needs to handle this sequence:

1. Create an authorization request for the read-only scope. Request offline access if a scheduled job needs access after the user leaves.
2. Bind the request to the user's session with a fresh `state` value.
3. In the callback, handle denied consent and verify `state` before exchanging the authorization code.
4. Store the returned credentials securely on the server, associated with the correct user.
5. Use the access token for API requests. Use the refresh token, when issued, to obtain later access tokens.

Don't assume every authorization response includes a new refresh token. Preserve an existing refresh token when a later response omits it.

## Confirm the account and property

Before debugging a complicated analytics request, list the properties available to the authorized account:

```bash
curl --fail-with-body \
  'https://www.googleapis.com/webmasters/v3/sites' \
  --header "Authorization: Bearer $GOOGLE_ACCESS_TOKEN"
```

The token must already be stored in `GOOGLE_ACCESS_TOKEN`. Google's [Sites: list reference](https://developers.google.com/webmaster-tools/v1/sites/list) describes the returned property identifiers and permission levels.

Use the exact returned property identifier in your next request. A Domain property such as `sc-domain:example.com` differs from a URL-prefix property such as `https://example.com/`.

If the property is absent, check which Google account authorized the app and whether that account has access in Search Console. Creating another OAuth client won't fix missing property permissions.

## When access stops working

Access tokens are short-lived. Read the token response's expiry information and let the client library refresh when appropriate, rather than assuming a fixed lifetime in your scheduler.

For an external OAuth app with publishing status **Testing**, Google generally issues refresh tokens that expire after seven days. The exception covers requests limited to basic identity scopes; Search Console's scope is outside that exception. See Google's [refresh token expiration rules](https://developers.google.com/identity/protocols/oauth2#expiration).

Refresh tokens can also become invalid after revoked access or other documented conditions. If refresh fails permanently, ask the user to authorize again. Repeating the same failed refresh indefinitely won't restore access.

| Symptom                         | Check first                                                  |
| ------------------------------- | ------------------------------------------------------------ |
| `redirect_uri_mismatch`         | Compare the request callback with the registered URI exactly |
| Consent was denied              | Stop the flow and let the user choose whether to retry       |
| API request is unauthorized     | Check token expiry, refresh outcome, and granted scope       |
| One property is forbidden       | Check account access and the exact property identifier       |
| Refresh returns `invalid_grant` | Check expiry or revocation, then reconnect if required       |

Once `sites.list` returns the expected property, make the [first Search Analytics request](/learn-google-search-console/api). Keep authentication diagnosis separate from filters and [quota errors](/learn-google-search-console/api/rate-limits).

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
