Running Claude on Google Cloud Vertex AI: Quotas and Service Accounts
Google Cloud Vertex AI puts Claude behind your existing GCP project: a service account authenticates the calls, project quota bounds how much traffic you can send, and a regional endpoint decides where inference actually runs.
Vertex AI authenticates differently from both the direct Anthropic API and Amazon Bedrock - there is no API key at all, only Google's Application Default Credentials resolved through a service account.
Three things need to exist before a call succeeds: a service account with the right IAM role, the Vertex AI API enabled with sufficient quota on the project, and a deliberate choice of region rather than an assumed default.
Missing any of those three produces a permission or quota error that looks like an SDK bug but is really a provisioning gap, the same failure shape as an unprovisioned Bedrock account.
This page covers service account setup, requesting and monitoring quota, and choosing between a specific region and Vertex AI's global routing, then shows the request shape application code actually uses.
from anthropic import AnthropicVertexclient = AnthropicVertex(project_id="my-gcp-project", region="us-east5")response = client.messages.create( model="claude-sonnet-5", max_tokens=1024, messages=[{"role": "user", "content": "Summarize this ticket in one sentence."}],)print(response.content[0].text)
When to reach for this:
Your organization already runs production workloads on Google Cloud and wants Claude usage to flow through existing IAM and billing.
You need Claude's traffic to stay inside a GCP-managed network and compliance boundary.
You want Claude spend to count against an existing Google Cloud committed-use discount.
You are integrating Claude into a service that already authenticates other GCP APIs via a service account.
import osfrom anthropic import AnthropicVerteximport anthropic# project_id and region are both required - there is no default project or region.client = AnthropicVertex( project_id=os.environ["GCP_PROJECT_ID"], region=os.environ.get("GCP_REGION", "us-east5"),)def summarize_ticket(ticket_text: str) -> str: """Call Claude on Vertex AI and return a one-sentence summary. Assumes Application Default Credentials resolve to a service account with the Vertex AI User role, and that the project has quota for claude-sonnet-5 in the target region. """ try: response = client.messages.create( model="claude-sonnet-5", max_tokens=200, messages=[ { "role": "user", "content": f"Summarize this support ticket in one sentence:\n\n{ticket_text}", } ], ) return response.content[0].text except anthropic.PermissionDeniedError: raise RuntimeError( "Service account lacks the Vertex AI User role, or the Vertex AI " "API is not enabled on this project." ) except anthropic.RateLimitError: raise RuntimeError( "Project quota exceeded for this model and region - request a " "quota increase in the Google Cloud console." )if __name__ == "__main__": ticket = "Customer reports login page returns a 500 error after the latest deploy." print(summarize_ticket(ticket))
What this demonstrates:
AnthropicVertex takes project_id and region as required constructor arguments - neither has a default, unlike the direct API's zero-argument client.
Authentication is entirely Application Default Credentials - there is no Anthropic API key anywhere in this code.
Catching PermissionDeniedError and RateLimitError separately turns the two most common first-deploy failures (missing IAM role, exhausted quota) into an actionable message.
Every Vertex AI request authenticates as a service account via Google's Application Default Credentials chain - locally this resolves through gcloud auth application-default login, and in production it resolves through whatever service account is attached to the compute environment (a GCE instance, a Cloud Run service, or a GKE workload identity binding).
The service account needs the Vertex AI User IAM role (or an equivalent custom role with the matching permissions) bound at the project or resource level before any call succeeds.
Enabling the Vertex AI API on the project is a separate step from IAM binding - a service account with the right role still fails if the API itself was never enabled for that project.
Quota is tracked per project, per model, and per region - a project with generous quota in us-east5 may have none in europe-west1 until a separate increase is requested there.
Region selection determines where inference actually executes: a specific region pins processing to that location, a multi-region value spans a geography, and "global" lets Anthropic route to whichever region has capacity.
# Create a service account dedicated to Claude API calls.gcloud iam service-accounts create claude-api-caller \ --display-name="Claude API caller"# Grant the Vertex AI User role, scoped to the project.gcloud projects add-iam-policy-binding my-gcp-project \ --member="serviceAccount:claude-api-caller@my-gcp-project.iam.gserviceaccount.com" \ --role="roles/aiplatform.user"# Enable the Vertex AI API if it isn't already.gcloud services enable aiplatform.googleapis.com --project=my-gcp-project
Creating a dedicated service account for Claude traffic, rather than reusing a broad general-purpose account, keeps IAM auditing straightforward and limits blast radius if credentials are ever compromised.
roles/aiplatform.user is the standard predefined role for invoking Vertex AI models; a narrower custom role is worth building once your permission needs are well understood.
Enabling the API is idempotent - running it again on an already-enabled project is a no-op, so it's safe to include in setup scripts.
Data residency or latency requirements that mandate a fixed location.
Multi-region (e.g. us, eu)
Routes within a geography, not a single data center.
Latency-sensitive workloads with a broad but bounded residency requirement.
"global"
Anthropic routes to the best available region.
Default choice when there is no residency constraint - maximizes availability during regional capacity limits.
Quota increases are region-scoped, so switching a workload from a specific region to "global" (or vice versa) later may require a fresh quota conversation, not just a code change.
A regulated workload that must keep processing inside a named jurisdiction should pin a specific region rather than use "global", even though "global" is the more resilient default for everything else.
from anthropic import AnthropicVertex# Streaming works identically to the direct API - only the client class differs.client = AnthropicVertex(project_id="my-gcp-project", region="us-east5")with client.messages.stream( model="claude-sonnet-5", max_tokens=512, messages=[{"role": "user", "content": "Draft a short release note."}],) as stream: for text in stream.text_stream: print(text, end="", flush=True)
AnthropicVertex exposes the same messages.create and messages.stream methods as the direct-API and Bedrock clients - code written against the direct API needs only a client-construction change to run on Vertex AI.
Installing the SDK with the vertex extra (pip install "anthropic[vertex]") pulls in the Google auth libraries the client needs; the plain anthropic package alone is not enough.
Assuming the direct API's zero-argument client pattern works here.AnthropicVertex() with no arguments raises immediately - both project_id and region are required. Fix: always pass both explicitly, typically sourced from environment configuration.
Service account has the IAM role but the Vertex AI API was never enabled. The role binding succeeds silently, but calls still fail. Fix: confirm aiplatform.googleapis.com is enabled on the project, not just that the IAM role exists.
Requesting quota in the wrong region. Quota is granted per region, so a quota increase approved for us-east5 does nothing for a client configured with region="europe-west1". Fix: match the quota request region to the client's configured region exactly.
Treating "global" as always the safest choice. For a regulated workload with a data residency requirement, "global" can route inference to a region outside the required jurisdiction. Fix: pin a specific region whenever residency is a hard requirement, and use "global" only when there is no such constraint.
Forgetting the vertex extra when installing the SDK. A plain pip install anthropic does not include the Google auth dependencies AnthropicVertex needs. Fix: install with pip install "anthropic[vertex]".
Reusing a broad, pre-existing service account instead of a scoped one. This makes IAM auditing for Claude-specific traffic much harder later. Fix: create a dedicated service account for Claude API calls with only the roles it needs.
Do I need an Anthropic API key to use Claude on Vertex AI?
No. Authentication is entirely through Google's Application Default Credentials, resolved to a service account - there is no separate Anthropic-issued API key involved.
Why does `AnthropicVertex()` raise an error with no arguments?
Both project_id and region are required constructor arguments with no defaults, unlike the direct API's client which can be constructed with zero arguments by reading an environment variable.
What IAM role does the service account need?
The roles/aiplatform.user predefined role, or an equivalent custom role with matching permissions
The Vertex AI API itself enabled on the project, which is a separate step from the IAM binding
How is quota scoped on Vertex AI?
Per project, per model, and per region. A quota increase approved for one region does not apply to a different region configured on the client.
What's the difference between a specific region, a multi-region value, and "global"?
A specific region pins inference to one location; a multi-region value routes within a geography; "global" lets Anthropic route to whichever region has capacity, which is the most resilient default absent a residency requirement.
Should a regulated workload use `region="global"`?
Usually not. A hard data residency requirement calls for pinning a specific region, since "global" can route inference outside a required jurisdiction.
Can the same application code run against both the direct API and Vertex AI?
Mostly, yes. Both clients expose the same messages.create and messages.stream methods - the differences are client construction (API key vs. project and region) and, for older dated-snapshot models, the model ID format.
Do current Claude model IDs need a prefix on Vertex AI?
No, for current-generation models the ID matches the direct API's bare model string. Dated-snapshot models use an @ version separator instead of a prefix.
What package extra do I need to install for Vertex AI support?
pip install "anthropic[vertex]" - the plain anthropic package does not include the Google auth dependencies AnthropicVertex requires.
Does streaming work the same way on Vertex AI as on the direct API?
Yes. client.messages.stream(...) behaves identically, including the text_stream convenience iterator.
Is enabling the Vertex AI API the same as granting IAM access?
No, they're separate steps. A service account can have the right IAM role while the API itself is still disabled on the project, and either gap alone causes calls to fail.
Why might a team choose Vertex AI over the direct API even though it's more setup?
To keep Claude traffic inside existing GCP IAM and network governance, and to have the spend count against an existing Google Cloud billing or discount agreement rather than a new vendor relationship.
Stack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the official anthropic Python SDK (latest 0.x release). Model names, pricing, and SDK versions move quickly - verify current specifics at platform.claude.com/docs before relying on them.
Reviewed by Chris St. John·Last updated Jul 18, 2026