gRPC-Web for browser clients with Apache APISIX

The APISIX grpc-web plugin translates browser gRPC-Web calls into native gRPC, so the decision is about content types, CORS and headers, and whether transcoding or an Envoy sidecar is simpler.

On this page

gRPC-Web for browser clients with Apache APISIX: what it solves

Your browser app needs to call gRPC services, but browsers cannot speak native gRPC over HTTP/2 with the trailers and framing that gRPC expects, so those services are usually unreachable from the front end. The APISIX grpc-web plugin translates gRPC-Web requests from browsers into native gRPC calls, and it accepts application/grpc-web and grpc-web-text content types. You need it when a browser client must invoke existing gRPC methods without a separate REST layer written for the front end. The plugin sits on the route in front of your gRPC upstream, so the services themselves do not change, and the browser client needs a gRPC-Web stub generated from the same .proto files the backend uses.

The plugin does not replace the rest of the gateway work. Authentication, rate limits and access rules still have to be configured on the route, and you should confirm how each of them behaves when the request arrives as gRPC-Web rather than native gRPC. It also does not change how the backend handles streaming. Browser support for streaming modes is narrower than for unary calls, so confirm with your front-end team which call types the app needs before you commit to this design. Check the plugin's current documentation for those limits, since the route and stub configuration depend on the APISIX version you run.

Before building, decide whether the browser really needs gRPC semantics. If the app only needs a few operations, a gateway-level JSON transcoding setup or a thin REST facade may be easier to test and hand over to your team. If you already run an Envoy sidecar for gRPC-Web, weigh that existing operating model against adding the same job to APISIX. The choice affects who maintains the proxy configuration, so settle it with the platform owner before the route design starts.

Configuration options for the grpc-web plugin and when each fits

This table compares the settings that shape how browsers reach gRPC services through the grpc-web plugin: content types, origin policy, allowed headers, preflight handling and route scoping. Read each row for the default behavior first, then the point at which a production team should tighten it. Confirm exact configuration keys in the plugin reference before writing any route definition.

SettingDefault behaviorWhen to tighten for production
Content types acceptedAccepts application/grpc-web and grpc-web-text requests and translates them into native gRPC callsKeep only the content type your client library actually sends, and confirm which text variant your generated stubs use before removing the other
Origin policy (CORS)Allows all origins by default, so any website can call the route from a browserRestrict to the exact origins of your web applications, and avoid wildcards on routes that carry authenticated calls
Allowed headersPermits the headers the plugin needs for gRPC-Web translation and preflightReview any custom metadata headers your clients send, and confirm the plugin passes them through as your services expect
Preflight (OPTIONS) handlingHandles OPTIONS preflight requests itself, so browsers get a response before the gRPC callKeep preflight handled at the gateway, and check that caching headers and allowed methods match your client behavior
Route scopingApplies to the routes where the plugin is configured, with no extra restriction by service or methodAttach the plugin only to the gRPC-Web routes that browsers use, and separate internal service routes from public browser routes
Authentication on browser routesPlugin defaults do not add authentication, so access depends on other plugins on the routePair the route with an authentication plugin and confirm that preflight requests are not blocked in a way that breaks sign-in flows
Method and service exposureAll gRPC methods reachable through the route are translated once the plugin is activeLimit the route to the services and methods the browser needs, and document which methods are intentionally exposed

CORS defaults, allowed headers and what to tighten

The grpc-web plugin handles preflight and origin checks on the gateway, so the CORS settings decide which browser apps can reach your gRPC services at all. Each decision below affects what a malicious page could send on behalf of a signed-in user.

Replace the all-origins default

The plugin allows all origins by default, which means any website a signed-in user visits can send requests to the gRPC endpoint through their browser. Decide the exact list of front-end origins your applications run on, including staging and preview hosts, and set that list explicitly. Check that no production route still inherits the open default after your configuration review.

Allow-list request headers

Browsers only send custom headers that the preflight response permits, so every metadata key your gRPC-Web client sends must be named in the allowed headers list. Include the content type headers gRPC-Web uses, plus the authorization header and any tracing or tenant headers your services read. Leave out headers the backend never reads, because each one widens what cross-origin requests can carry.

Control the authorization token path

Bearer tokens travel in the authorization header, so the allowed headers decision is also an authentication decision. Confirm which token type your browser clients hold, where it is stored, and whether the gateway or the gRPC service validates it. Avoid putting long-lived credentials into browser storage, and check that expired tokens fail at the gateway with a clear error.

Decide how credentials cross origins

Cookies and HTTP authentication are sent cross-origin only when the browser request sets credentials and the server answers with an explicit origin and credentials permission. Browsers refuse a wildcard origin in that case, so an all-origins setting and credentialed requests do not work together. Pick one model per application: token-in-header with no cookies, or cookie-based sessions on a single trusted origin, and test the chosen combination in a browser.

Expose only the response headers you need

Browsers hide most response headers from scripts unless they are listed as exposed. gRPC-Web clients depend on trailers and status fields that arrive in response headers, so check which ones your client reads and expose only those. Keep internal headers such as upstream addresses or server versions off the list, since they help attackers map your backend.

Review the policy on every change

New front-end hosts, new metadata keys and new services each change the CORS policy, and the change often lands in a different place than the gRPC route it affects. Assign an owner for the origin list, keep it in version-controlled configuration, and add a test that sends a preflight from an unlisted origin and expects a refusal. Confirm the exact behavior of your APISIX version in the plugin reference before you rely on it.

Setting up grpc-web on an APISIX route

This sequence takes a gRPC service that browsers cannot call directly and exposes it through an APISIX route with the grpc-web plugin, restricted origins and headers, and checks that a browser and a preflight request both succeed. Each step ends with a check so the team knows it can move on.

  1. Confirm the gRPC service and its proto definitions

    The service owner and the team that will run the gateway confirm the service name, the methods browsers need, and the .proto files that define them. They also confirm that the backend serves native gRPC over HTTP/2 and where its TLS certificate comes from. The step is done when someone can point to the exact proto version the frontend will generate client code from, and when a direct gRPC call to the backend succeeds from a test host.

  2. Deploy APISIX in the target environment

    The platform team installs APISIX in the infrastructure you control, using the deployment mode and packaging your environment supports. The official getting started guide covers installation steps and the default ports, including port 9080 for client traffic and port 9180 for the Admin API in traditional mode. The step is done when the gateway starts, answers on the client port, and the Admin API responds to an authenticated request.

  3. Create an upstream with the gRPC scheme

    Create an upstream that points to the backend and set its scheme to the gRPC variant that matches the backend's transport, either plaintext or TLS. Confirm the backend host, port and health behavior in the same object. The check is a route-independent test: sending a request through the gateway to the upstream without the browser layer should reach the service and return a gRPC response, which confirms the upstream before any browser logic is added.

  4. Attach the grpc-web plugin to the route

    Create a route that matches the gRPC-Web path prefix your frontend uses and points to the upstream, then enable the grpc-web plugin on that route. Per the plugin documentation, the plugin translates application/grpc-web and grpc-web-text requests into native gRPC calls and, by default, allows all origins and handles OPTIONS preflight. The check is that a request with a gRPC-Web content type returns a response the backend produced, not a 404 or a gateway error.

  5. Restrict origins and allowed headers

    Because the default CORS behavior accepts all origins, replace it with an explicit list of the front-end origins that should call the service, and limit allowed request headers to those the application actually sends. Confirm that the CORS settings you choose match the plugin's documented options for your APISIX version. The check is a request from an origin not on the list being refused by the browser, while a listed origin is accepted.

  6. Verify with a browser client and a preflight test

    Run the generated gRPC-Web client from the approved front-end origin and confirm a unary call completes end to end through the gateway. Separately, send an OPTIONS request with the origin, requested method and headers you expect, and confirm the response carries the allow headers you configured. Record the results with the APISIX version and the plugin configuration, so the same test can run again after upgrades. The step is done when both checks pass and a rejected origin fails as expected.

When Envoy or JSON transcoding is the simpler option

If your services already run behind Envoy, whether as a sidecar in a service mesh or as a shared edge proxy, the browser's gRPC-Web traffic may already be handled there. Adding a second translation layer through APISIX then means two places where gRPC-Web headers, CORS behavior and timeouts are configured and debugged. Keeping translation in the proxy your platform team already operates usually keeps the control plane smaller.

  • Configuration ownership: Confirm which team owns the Envoy listener and whether it already performs gRPC-Web translation for browser origins.
  • Policy placement: Decide whether authentication, rate limits and logging should run in APISIX or in the mesh, so that one policy is not enforced twice.
  • Upgrade coupling: Envoy and mesh releases follow their own schedules, so check how an APISIX upgrade interacts with that proxy chain.
  • Operational skills: Your on-call engineers may already know Envoy's stats and access logs better than APISIX's, which affects incident response.
  • Proto distribution: Mesh setups often generate stubs from a shared proto repository, which can simplify keeping browser and backend definitions in step.

Before choosing, ask your platform team to document the current browser path end to end, including every proxy a request crosses.

Security and operational considerations for browser gRPC access

Once the grpc-web plugin is live, the browser path becomes a public entry point into your gRPC services. The cards below cover the controls that decide whether that entry point stays narrow, and each one names what to verify in your own environment before go-live.

Origin policy and CORS scope

The grpc-web plugin allows all origins and handles OPTIONS preflight by default, so an unchanged route accepts browser calls from any site. Set the allowed origins to the exact scheme, host and port of each front end, and confirm that preflight responses only expose the headers your client sends. Test with a page served from an origin you did not list, and confirm the browser blocks the call.

Authentication at the route

Preflight requests carry no credentials, so CORS does not protect the RPC itself. Attach an authentication plugin such as jwt-auth or openid-connect to the same route that carries the grpc-web plugin, and confirm that unauthenticated POST requests with the grpc-web content types are rejected before they reach the backend. Verify that tokens travel in headers the browser client can set and that expired tokens fail cleanly.

Rate limits per method and client

Browser clients are easy to script, so a public gRPC-Web route can be called at volumes no human user would produce. Apply traffic control plugins keyed on the consumer or client address, and decide whether limits differ between read and write methods. Load test the route with realistic message sizes, since a limit set on request count alone does not cap the cost of large payloads.

TLS on both hops

Decide where TLS terminates for each hop: from the browser to APISIX, and from APISIX to the gRPC backend. Confirm the certificate chain presented to browsers is trusted by the browsers you support, and that the upstream connection validates the backend certificate instead of skipping verification. Record which certificates belong to which team and when each one expires.

Logging browser requests

Access logs for browser traffic show the origin, user agent and route, which helps when a rate limit or auth rule blocks a legitimate user. Decide which fields to log and which to exclude, because request bodies may contain personal data. Confirm that log retention and access to logs match your data handling policy, and that the logs record enough to trace one request from the browser through to the backend.

Plugin and APISIX version currency

The grpc-web plugin ships with APISIX, so security fixes arrive through gateway upgrades. Track the APISIX release you run against the project's downloads page, which lists the latest APISIX 3.19.0 release and notes no release as long-term support. Schedule a regular review of the release notes, test the grpc-web route after each upgrade, and confirm who approves a version change.

Questions teams ask before building browser gRPC access

How much effort does browser gRPC access take with APISIX?

Effort depends mostly on how many services and methods the browser must reach, not on the gateway configuration itself. Each service needs its proto files compiled for the browser client, a route on the gateway, and a decision about which methods are exposed. Teams with a small, stable set of services usually finish faster than teams with dozens of services that change often. Ask any partner to break the estimate into proto inventory, route design, CORS policy, authentication, and browser testing, so each part can be checked against your own service list.

What drives the cost of a browser gRPC project?

The main cost drivers are:

  • The number of gRPC services and methods, and how many of them change each sprint
  • How clean the proto files are, including shared messages, versioning and generated code for the browser
  • The CORS policy, since each allowed origin needs a decision and a test
  • How browser calls authenticate against your identity provider
  • How much testing is needed across the browsers your users run

Costs are one-time for the initial build and recur when services or origins change. Ask for a quote that separates these items and states which ones are one-time and which ones are ongoing.

How long does it take to expose gRPC services to a browser?

Duration follows the same drivers as effort: the number of services, the state of the proto files, and the number of origins and authentication paths. A team with a short service list and clean protos can often stage a working route quickly, while a broad rollout across many services needs more time for testing and rollout. Confirm the schedule in the written scope, including which services are in the first release and what acceptance tests apply.

What must our team provide before the work starts?

Three inputs carry most of the early work:

  • The proto files for every service the browser will call, with their owners and version history
  • A named service owner for each service who can approve method exposure and answer contract questions
  • The list of browser origins that should be allowed, including staging and any partner domains

You should also provide the authentication model your identity provider uses and access to a staging environment where the gateway can be tested. Missing inputs usually cause the most delay, so settle them before scope is signed.

Can our in-house team build browser gRPC access without a partner?

Yes, a team with gRPC, Apache APISIX and frontend experience can build it internally. The work is manageable when the service count is small and one team owns the protos, the gateway and the browser client. Partners add the most value when several teams share the gateway, when CORS and authentication rules must be reviewed by security, or when the team lacks time for cross-browser testing. Compare the internal effort against the scope you would write for a partner.

Which CORS settings should we review before going live?

The grpc-web plugin accepts both application/grpc-web and grpc-web-text content types and handles OPTIONS preflight requests. By default it allows all origins, which is rarely acceptable for a regulated environment. Review the allowed origins, headers and methods explicitly, and confirm that credentials are only allowed for origins you trust. Your security team should sign off on the origin list, and tests should confirm that unlisted origins are refused. Check the current plugin settings against the APISIX grpc-web documentation before you write the policy.

How should we test browser gRPC access across browsers?

Test the full path from the browser client through the gateway to the upstream service, not only the gateway alone. Cover the content types your client sends, preflight handling, rejected origins, authentication failures and error responses. Run the same test set on each browser your users rely on, and repeat it after every proto change or gateway upgrade. Ask any partner to describe the test matrix and the evidence it produces, so your own team can rerun it later.

Is an Envoy sidecar or JSON transcoding a simpler option?

It can be. If the browser only needs a few read-only methods, JSON transcoding through a REST-style route may be simpler to build and debug than generated browser clients. An Envoy sidecar is worth evaluating when your platform already runs Envoy and your team knows how to operate it. Decide by comparing the number of methods, the streaming needs, the existing platform skills and the long-term ownership of each option, then document the choice so future teams know why it was made.

Limits to confirm in your environment

The grpc-web plugin covers a narrow set of browser cases, and its defaults are permissive. Each card below names one thing to confirm against the plugin documentation or your own tests before the design is fixed, so the browser path does not surprise the team after launch.

Supported gRPC-Web modes

The plugin documentation names the application/grpc-web and grpc-web-text content types. Confirm whether your client library sends any other framing or header variant, and whether the plugin treats it as pass-through or rejects it. Test each content type your frontend build actually emits, including the text variant used for server-streaming responses, against a staging route before you commit to the design.

Streaming behavior

Unary calls are the simplest case for a browser. Server-streaming and bidirectional patterns depend on how the gateway buffers and forwards HTTP/2 frames to the browser, and browsers have no native client streaming over fetch. Ask for the documented behavior for each RPC type you plan to expose, and test long-running streams for idle timeouts and early connection closure at the gateway and at any load balancer in front of it.

Browser compatibility

gRPC-Web is consumed by browser client libraries rather than the browser itself, so support depends on the generated client and the browsers in your user base. Build a short matrix of browser versions, operating systems and corporate proxy setups that your customers use. Include the restricted networks in your environment, where intermediaries may alter headers or block the text content type.

CORS and header defaults

By default the plugin allows all origins and handles OPTIONS preflight. Decide which origins, methods and custom headers your application needs, then override the defaults in the route configuration and confirm with a preflight test. Check that any authentication header your browser sends is listed as allowed, or the request fails before it reaches the upstream.

Fit with your APISIX release

Plugin behavior can change between releases, and the downloads page does not mark any release as long-term support. Pin the APISIX version you plan to run, read the release notes for the grpc-web plugin and any gRPC change that affects it, and rerun your browser test suite before each upgrade. Confirm the support status of that release with the project before you commit to a production date.

How DeployOpen scopes and delivers browser gRPC access on APISIX

DeployOpen plans, implements, tests and documents gRPC-Web access through Apache APISIX inside infrastructure you control. We start by fixing which browser clients, gRPC services and content types are in scope, then build the grpc-web route, CORS and header settings against that list, and hand over working configuration with the runbooks your team needs.

How we scope

  • Inventory which browser applications and gRPC services need access through the gateway and which methods they call.
  • Confirm the grpc-web content types each client sends, and whether the team needs grpc-web-text or binary framing.
  • Record CORS origins, allowed headers and authentication requirements in a written scope before any build work starts.

How we build

  • Configure the grpc-web plugin on routes in a staging APISIX environment, replacing the default allow-all origin policy with your listed origins.
  • Set allowed headers and OPTIONS preflight handling, then test each browser client against the route with its real credentials.
  • Compare the grpc-web route with an Envoy sidecar or JSON transcoding option where the team's service design points that way, and document the decision.

How we hand over

  • Deliver versioned route and plugin configuration, with the CORS and header policy stored as code in your repository.
  • Provide test scripts that send preflight and gRPC-Web requests, so your team can rerun verification after each change.
  • Document the operating steps for adding origins, rotating certificates and upgrading the APISIX version in your environment.

How we support

  • Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
  • Ongoing support, upgrades and continuous testing for the gateway are available as a retainer.
  • Ask for a written quote based on your scope, since DeployOpen does not publish a price list.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.