Skip to content

gRPC-Web — Complete Guide

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about grpc. We cover key concepts, practical examples, and best practices to help you master this topic.

gRPC-Web brings gRPC to browser applications. Browsers cannot directly use HTTP/2 trailers or bidirectional streaming required by native gRPC. gRPC-Web uses a proxy (Envoy) to translate between browser-compatible HTTP/1.1 and native gRPC.

What You'll Learn

  • gRPC-Web architecture and proxy pattern
  • Envoy proxy configuration for gRPC-Web
  • Client-side gRPC-Web libraries
  • Limitations compared to native gRPC
  • Protocol differences (no trailers, no bidirectional streaming)

Why It Matters

Many applications need browser clients to consume gRPC services directly. gRPC-Web removes the need for a REST translation layer, enabling efficient web clients with protobuf Serialization.

Real-World Use

Square uses gRPC-Web for their browser-based POS system. Improbable uses it for spatial OS web clients. The gRPC-Web spec is used by Envoy and Nginx for web-gRPC bridging.

flowchart LR
    Browser[Browser Client] -->|gRPC-Web HTTP/1.1| Proxy[Envoy Proxy]
    Proxy -->|Native gRPC HTTP/2| Server[gRPC Server]
    Browser --> ProtoBuf[protobuf via JSON or binary]
    Proxy --> Translate[Translate: gRPC-Web <-> gRPC]

Teacher Mindset

gRPC-Web is not native gRPC. It cannot use bidirectional streaming. Use Envoy as the proxy layer. The browser sends requests as HTTP/1.1 and the proxy converts to HTTP/2 for the backend.

Code Examples

# Example 1: Envoy configuration for gRPC-Web
static_resources:
  listeners:
    - name: grpc_web_listener
      address:
        socket_address: { address: 0.0.0.0, port_value: 8080 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                codec_type: AUTO
                stat_prefix: grpc_web
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: backend
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/" }
                          route:
                            cluster: grpc_backend
                http_filters:
                  - name: envoy.filters.http.grpc_web
                  - name: envoy.filters.http.router
  clusters:
    - name: grpc_backend
      type: LOGICAL_DNS
      typed_extension_protocol_options:
        envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
          "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
          explicit_http_config:
            http2_protocol_options: {}
      load_assignment:
        cluster_name: grpc_backend
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address: { address: localhost, port_value: 50051 }
// Example 2: gRPC-Web client in TypeScript
import { GrpcWebFetchTransport } from "@protobuf-ts/grpcweb-transport";
import { OrderServiceClient } from "./generated/orderservice.client";

const transport = new GrpcWebFetchTransport({
  baseUrl: "http://localhost:8080",
});

const client = new OrderServiceClient(transport);

async function getOrder() {
  const { response } = await client.getOrder({ orderId: "123" });
  console.log("Order:", response);
}
// Example 3: Error handling in gRPC-Web
client.getOrder(
  { orderId: "123" },
  (err, response) => {
    if (err) {
      // gRPC-Web errors include code and message
      console.error(`gRPC error ${err.code}: ${err.message}`);
      return;
    }
    console.log("Order:", response.toObject());
  }
);

Common Mistakes

  • Expecting bidirectional streaming support in gRPC-Web (not supported)
  • Forgetting to configure the grpc_web filter in Envoy
  • Using native gRPC client libraries in the browser (they do not work)
  • Not handling CORS configuration for the Envoy proxy
  • Using gRPC-Web without considering binary vs JSON encoding trade-offs

Practice

  1. Set up an Envoy proxy with gRPC-Web filter.
  2. Install a gRPC-Web client library in a frontend project.
  3. Generate client stubs with protoc-gen-grpc-web.
  4. Call your order service from a browser application.
  5. Challenge: Create an Angular/React component that displays gRPC-Web data with proper error handling.

FAQ

What is the difference between gRPC and gRPC-Web?

gRPC requires HTTP/2 and supports bidirectional streaming. gRPC-Web works over HTTP/1.1 and only supports unary and server-streaming.

Do I need Envoy for gRPC-Web?

Envoy is the most common gRPC-Web proxy. Other options include Nginx, Traefik, and the gRPC-Web Go proxy.

Can I use gRPC-Web without a proxy?

Some gRPC servers support gRPC-Web natively (improbable-eng/grpc-web). However, a proxy is the standard pattern.

Does gRPC-Web support protobuf binary or only JSON?

gRPC-Web supports both binary protobuf and JSON. Binary is more efficient. JSON aids debugging.

How do I handle authentication with gRPC-Web?

Send auth tokens in HTTP headers. The Envoy proxy forwards them to the gRPC server as metadata.

Mini Project

Add a browser frontend to your order service. Set up Envoy as a gRPC-Web proxy. Generate TypeScript client stubs. Create a simple HTML page that displays orders fetched via gRPC-Web.

What's Next

Next, you will learn about gRPC-Gateway for exposing gRPC services as REST APIs.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro