Semantic Embedder API

Dev Trial

The Semantic Embedder API generates high-dimensional vector representations (embeddings) of text directly on the user's device. It unlocks semantic search, retrieval-augmented generation, and real-time content intelligence without the latency, cost, and privacy trade-offs of cloud embedding services — or the storage bloat of every site shipping its own model.

Developer Trial: This API is in an early developer trial. To use it, run Chrome Canary and enable the #semantic-embedder-api flag in chrome://flags. It has not yet been approved to ship, and the shape of the API — including the SemanticEmbedder name itself — is still an open question.

Use cases

Semantic search

A note-taking app can find notes by meaning rather than keywords, entirely on-device and private to the user.

RAG

A documentation site can build an offline-capable Q&A bot that retrieves the most relevant passages before prompting a model.

Content intelligence

A community forum can flag potentially toxic comments as the user types, before the content is ever sent to a server.

SemanticEmbedder.availability()

Checks whether an embedding model is available on this device, allowing progressive enhancement. The API follows the same availability → create → execute pattern as the other Built-In AI APIs.

staticavailability(): Promise<Availability>;

Returns

A promise that resolves to an Availability string: 'available', 'downloadable', 'downloading', or 'unavailable'.

Interactive Playground

SemanticEmbedder.create()

Instantiates a new SemanticEmbedder object, initiating any necessary model download. As with the other Built-In AI APIs, expect the standard signal and monitor options for aborting creation and tracking download progress.

staticcreate(options?: SemanticEmbedderCreateOptions): Promise<SemanticEmbedder>;
Interactive Playground
Advanced model parameters are explicitly out of scope for the initial proposal. One option under discussion is an optional taskType hint that browsers may safely ignore if the underlying model does not support it. The proposed values are "semantic-similarity", "retrieval-query", "retrieval-document", "classification", and "clustering". For retrieval, embed your corpus with "retrieval-document" and the user's query with "retrieval-query".

semanticEmbedder.embed()

Embeds the input and returns a structured EmbedderResult. The method is polymorphic: pass a single string, or an array of strings to embed a whole batch in one call.

embed(input: DOMString | sequence<DOMString>): Promise<EmbedderResult>;

Returns (EmbedderResult)

PropertyTypeDescription
embeddingssequence<Embedding>The generated embeddings, corresponding strictly 1:1 with the inputs provided in the batch.
embeddings[i].valuesFloat32ArrayThe raw vector for that input.
embeddings[i].statisticsEmbeddingStatisticsProposed for future extensibility: usage information such as tokenCount and truncated.
metadataEmbedderMetadataModel compatibility information exposing the embeddingSpace identifier. A maxInputTokens field is proposed as future extensibility.

A dictionary is returned rather than a raw array so the API can be extended later — with token consumption statistics, truncation warnings, or multi-modal metadata — without breaking backwards compatibility for early adopters.

Example Output

semanticEmbedder.destroy()

Destroys the embedder instance, allowing the browser to unload the underlying model from memory. Because embedding is stateless, you should proactively destroy the embedder as soon as a batch is done.

destroy(): undefined;
Interactive Playground

API reference

The explainer does not yet publish formal WebIDL. The interface below is reconstructed from the examples and prose in the proposal, and is the shape you should expect to code against during a developer trial — not normative spec text.

Members marked // under discussion appear in the explainer as open questions or future extensibility, not as committed surface.
Interactive Playground

Members at a glance

MemberReturnsStatus
SemanticEmbedder.availability()Promise<Availability>Proposed
SemanticEmbedder.create()Promise<SemanticEmbedder>Proposed
semanticEmbedder.embed()Promise<EmbedderResult>Proposed
semanticEmbedder.destroy()undefinedProposed
SemanticEmbedder.compare()doubleUnder discussion — would validate embedding-space compatibility before comparing.
SemanticEmbedder.chunk()sequence<DOMString>Under discussion — native splitting of large documents.
options.taskTypeDOMStringUnder discussion — optional quality hint that browsers may ignore. Values: "semantic-similarity", "retrieval-query", "retrieval-document", "classification", "clustering".

Comparing embeddings

The API returns raw vectors, so semantic closeness is measured with a distance function you supply — most commonly cosine similarity. A built-in static utility (e.g. SemanticEmbedder.compare()) is under discussion; it could also validate that both vectors come from the same embedding space before comparing them.

Interactive Playground

Batching for document retrieval

For RAG or document search you typically embed many passages at once. Pass an array to embed() and store the resulting vectors in local storage such as IndexedDB or OPFS — the API deliberately provides no built-in vector database.

Interactive Playground

Chunking and truncation

The API does not automatically chunk large text inputs. You must pre-chunk documents yourself to stay within the API's proposed 2048-token input limit and pass the chunks as an array. Two practical strategies:

  • Maximum efficiency: use an offline tokenizer to estimate a domain-specific character-to-token ratio, then chunk rapidly by character length in the browser.
  • Strict accuracy: load the model's open-sourced tokenizer and use it as the length function of a splitter such as LangChain's RecursiveCharacterTextSplitter, counting exact tokens while merging segments.

A native helper (e.g. SemanticEmbedder.chunk()) is one of the open questions being explored.

Embedding space and compatibility

Embedding vectors are mathematically tied to the model that generated them — vectors from different embedding spaces cannot be compared. That is why EmbedderResult carries an EmbedderMetadata dictionary exposing the embeddingSpace identifier: it lets you version your local vector database, know when to re-index after a model update, and determine which cloud-side models your vectors are compatible with.

Initial prototypes are expected to use spaces from open-weight models such as EmbeddingGemma (google/embeddinggemma-300m) or Qwen3-Embedding-0.6B to maximize compatibility with server-side embeddings.

Non-goals

Out of scopeWhat to do instead
Integrated storageNo built-in vector database. Store and search embeddings with existing Web Platform storage such as IndexedDB or OPFS.
Model trainingInference only. Training and fine-tuning on device are not supported.
Complex ML knobsAdvanced model parameters are not exposed initially; the focus is on core functionality.

Security and privacy

  • Permissions policy: access is gated by a permissions policy restricted to top-level frames and same-origin iframes by default. Third-party contexts must be explicitly granted access.
  • Sandbox isolation: data processing and model execution occur in a sandboxed environment to mitigate the risk of malicious inputs.
  • Statelessness: other than model download state, the API keeps no memory or user data across sessions.