How to detect Meta's Muse AI agent

Detect Muse from ARM Linux client hints and SwiftShader, then route agents to your API instead of a human form.

13 min read
In short: Meta's Muse is a personal agent whose Chromium browser does not identify itself with a User-Agent name or HTTP message signatures. Recognize it from layered browser signals – SwiftShader software rendering plus an ARM architecture client hint on a reduced Linux user agent – then deny the form and point the agent at your API or MCP server.

What is Meta's Muse?

Meta's Muse is a personal agent whose Chromium browser does not name itself in the User-Agent header or sign requests. Detect Muse by combining SwiftShader software rendering with an ARM architecture client hint on Chrome's reduced X11; Linux x86_64 Linux user agent, then deny human-only forms and point agents at your API.

Meta launched Muse on September 8, 2026. Muse opens a browser, reads pages, fills in forms, and completes purchases. Each person gets a Linux virtual machine in the cloud, with a Chromium-based browser that the person can watch and take over. Muse browser requests look like Chrome on Linux: no agent name in the User-Agent header, no Signature-Agent header, and no page automation markers.

console.dev, a weekly developer tools newsletter, uses this pattern. The console.dev subscribe form is for people. Agents use the console.dev API and MCP server. Arcjet Advanced Signals protects the form so automated signups stay off the mailing list and agents use the API instead.

For more information about named agents and request signatures, see How to identify AI agents and bots. For more information about classifying agents that hit your forms, see AI agent bot management.

What does Muse look like to your server?

Muse is an ordinary Chrome-on-Linux form submission from the server's point of view. The Muse User-Agent claims Chrome 154 on Linux, and the accompanying headers match a real browser POST:

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/154.0.0.0 Safari/537.36

According to the Chromium release schedule, Chrome 154 reached the stable channel on September 22, 2026. That date fits Meta's description of "a real up-to-date Chromium based browser". Headers, IP addresses, and page automation fingerprints still do not name Muse, so recognition depends on browser environment signals.

Do Muse headers identify the agent?

Muse request headers do not identify the agent. Muse sends Sec-CH-UA for Chromium 154, Sec-CH-UA-Platform as "Linux", and Sec-Fetch-*, Origin, and Referer values that match a real form submission. The Muse user agent has no agent name, and the Muse request has no Signature-Agent header, so the usual ways to identify an AI agent don't apply.

According to Meta, "When Muse browses the internet, it will appear as your activity." When Amazon blocked Muse from its store in September 2026, Amazon said Muse doesn't identify itself. Cloudflare Radar lists a Muse client with the user agent prefix muse-, but the Muse browser requests that we observed sent the standard Chrome user agent instead.

Do Muse IP addresses or page fingerprints identify it?

Muse IP addresses do not identify the agent. The Muse request that we observed came from a US mobile network, not a cloud provider. According to Peter James's teardown of Muse's browser stack, Muse routes browser traffic through residential exits near the person's location, so a rule that blocks data center IP addresses doesn't apply.

Muse page fingerprints do not identify the agent either. Meta describes a browser sub-agent that works from an accessibility tree snapshot, can't run JavaScript in the page, and drives Chromium through a separate broker with DevTools turned off. In that Muse browser environment, navigator.webdriver is false, and the page has no automation globals or patched browser APIs. To recognize Muse, look at the environment that the Muse browser runs in.

Why isn't one signal enough?

SwiftShader alone is not enough to detect Muse, because software rendering still appears on real machines. Muse's WebGL renderer is SwiftShader, Chromium's CPU implementation of the Vulkan and OpenGL ES graphics APIs:

ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (LLVM 10.0.0) (0x0000C0DE)),
SwiftShader driver)

Chrome used to fall back to SwiftShader automatically when Chromium couldn't use a GPU. Since late 2025, Chrome no longer does that. SwiftShader now renders WebGL only when a command-line flag or the EnableUnsafeSwiftShader enterprise policy turns SwiftShader on. Chromium documents that flag for testing on servers without a GPU, and the enterprise policy exists for managed virtual machines and remote desktops. A rule that denies on software rendering alone blocks real subscribers.

Advanced Signals treats SwiftShader as reputation evidence. Each signal adds to a score, and Signals denies a request only when enough independent signals agree. For more information about why Arcjet scores this way, see Bot detection isn't perfect. To recognize Muse, Signals needs a second signal that doesn't depend on the renderer.

How do CPU architecture client hints help?

CPU architecture client hints help detect Muse because the Muse browser reports arm while the reduced Linux user agent says X11; Linux x86_64. Those values describe Chromium on ARM Linux, not a spoofed architecture token.

Chromium exposes the real architecture through User-Agent Client Hints. Since Chrome 107, User-Agent reduction freezes the platform token. On Linux, the reduced user agent always says X11; Linux x86_64, whatever the CPU. The client hint is the only place where the real architecture appears.

ARM Linux Chromium includes people as well as agents. First, Raspberry Pi owners, whose default browser is Chromium unless Firefox is chosen. Second, people who run Linux on ARM laptops. Third, developers who run a Linux virtual machine on an Apple silicon Mac. Windows on ARM laptops also report arm, but the Windows user agent says Windows NT 10.0; Win64; x64, and Signals ignores architecture for those laptops.

How do the two signals combine?

Software rendering means that the Muse browser has no GPU. The architecture hint means that the Muse machine runs ARM Linux. Together those signals describe an ARM Linux machine without a GPU. Meta doesn't publish the hardware that the Muse browser runs on. According to the browser stack teardown, the Muse browser runs on a separate virtual machine leased from a pool of machines built for browser tasks.

The people most likely to match both signals are developers who run Chromium in an ARM Linux virtual machine without GPU passthrough. On a form that's meant for people, Arcjet accepts that tradeoff. Advanced Signals weights the architecture check more heavily than the renderer, but not enough to deny a request on architecture alone. When Muse submitted the console.dev subscribe form, Signals denied the Muse request and reported both signals.

How do you read the signals yourself?

Read Muse-like signals in the browser with navigator.userAgentData.getHighEntropyValues(["architecture"]) for the CPU architecture and the WEBGL_debug_renderer_info extension for the renderer string. Send both values to your server and score those values with your other bot signals. For example, the following function reads the architecture and renderer in the browser:

async function browserEnvironment() {
// User-Agent Client Hints are Chromium-only and need a secure context.
const uaData = navigator.userAgentData;
const { architecture = "" } = uaData
? await uaData.getHighEntropyValues(["architecture"])
: {};
const gl = document.createElement("canvas").getContext("webgl");
const debug = gl?.getExtension("WEBGL_debug_renderer_info");
const renderer = debug ? gl.getParameter(debug.UNMASKED_RENDERER_WEBGL) : "";
return { userAgent: navigator.userAgent, architecture, renderer };
}

The following function checks for the ARM Linux plus SwiftShader combination that this article describes:

function looksLikeArmLinuxVm({ userAgent, architecture, renderer }) {
const linuxUserAgent = userAgent.toLowerCase().includes("linux x86_64)");
const arm = architecture === "arm" || architecture === "arm64";
const softwareGpu = /swiftshader/i.test(renderer);
return linuxUserAgent && arm && softwareGpu;
}

A browser can forge anything that the browser reports. Treat these values as one input to a score, and check the telemetry for signs of tampering. Advanced Signals does both. Firefox and Safari don't support User-Agent Client Hints, so a missing architecture value isn't evidence of anything. To read the architecture without JavaScript, respond with an Accept-CH header that includes Sec-CH-UA-Arch. Chromium then sends a Sec-CH-UA-Arch header on later requests to your origin.

What does Muse report in production?

Our analysis of Arcjet global platform traffic found that the Muse browser typically reports Chrome 154 on X11; Linux x86_64, client-hint architecture arm, SwiftShader through ANGLE on Vulkan, 6 logical CPUs, and about 16 GB of device memory. Treat those Muse hardware values as unstable; the durable signal is ARM Linux without a GPU.

Muse's browser reports a consistent profile across that traffic:

PropertyValue
User agent

Chrome 154 on X11; Linux x86_64

Client hint brands

Chromium only, with no Google Chrome

Client hint architecturearm
WebGL rendererSwiftShader through ANGLE on Vulkan
Logical CPU cores6
Device memory16 GB, sometimes 8 GB
ScreenUsually 1920×1080
Speech synthesis voicesNone
Time zoneVaries

Which Muse values should you avoid matching?

Browsers round some Muse environment values. For example, navigator.deviceMemory reports a power of two, and since Chrome 147 desktop Chrome reports up to 32 GB. These Muse values describe the machine that runs the browser, not the virtual machine that runs the agent.

According to Rohan Adwankar's teardown of the Muse agent virtual machine, the agent VM has 2 virtual CPUs and 8 GB of memory on an x86 host. The browser stack teardown also found a fallback: if Muse can't lease a browser machine, Muse runs the browser inside the agent's own virtual machine. A browser on that fallback path runs on x86, so that browser doesn't report arm.

Don't write a rule that matches the Muse core count, memory, or screen size. Meta can change those virtual machine settings at any time, and each value is common on real devices. The Muse environment, an ARM Linux machine without a GPU, is a more reliable signal. Meta could change that too, for example by moving to x86 hosts or adding GPUs.

How do you send agents to the right interface?

Send Muse and other browser agents to your API by denying the human form and returning a response that points to your agent interface. Advanced Signals tells your application that a browser agent is submitting the form; your application decides what to do next.

On console.dev, the decision follows from what each interface is for. The console.dev subscribe form is for people. Agents use the console.dev API or MCP server, and an agent that acts for a real person still has a supported way to subscribe them. Denying automated form submissions keeps bulk signups off the mailing list without closing that path.

According to Meta's post on personal agents and businesses, a business should be able to "refer the agent to skills and connectors that work better at scale", so that Muse can "follow the business's preferred path". Meta and Sierra are developing the Personal Agent Protocol as an open standard for this. The Personal Agent Protocol was announced in October 2026, and the specification is still a draft.

How do you enforce this with Arcjet?

To enforce Muse detection with Arcjet, deny the form submission and return a response that points to your API. The following route handler uses the Arcjet Next.js SDK:

import arcjet, { detectBot } from "@arcjet/next";
import { NextResponse } from "next/server";
const aj = arcjet({
key: process.env.ARCJET_KEY!,
rules: [
detectBot({
mode: "LIVE",
allow: [], // deny every detected bot on this form
}),
],
});
export async function POST(req: Request) {
const decision = await aj.protect(req);
if (decision.isDenied()) {
return NextResponse.json(
{
error: "This form is for people. Agents can use the API.",
docs: "https://example.com/developers",
},
{ status: 403 },
);
}
// Add the subscriber.
return NextResponse.json({ status: "accepted" });
}

Arcjet reports requests that Signals denies with ARCJET_SIGNALS as the bot reason. To see how often agents reach a form before you enforce anything, set mode to "DRY_RUN" first. Agents can also identify themselves. ChatGPT's cloud browser signs ChatGPT requests with HTTP message signatures, so a site can verify the agent instead of inferring the agent from the browser environment.

Meta says that the Personal Agent Protocol is meant to address how agents "can securely convey user identity", but the Muse requests that we observed weren't signed. Until Muse requests are signed, recognizing Muse depends on several weak signals that agree with each other. To recognize Muse and other browser agents on your forms, add the Signals script to the pages that lead to those forms, and configure detectBot in the route handler. The Advanced Signals documentation includes examples for Next.js, Python, and other frameworks.

Frequently asked questions

Does Muse identify itself in the User-Agent header?

Muse browser requests that we observed sent a standard Chrome-on-Linux User-Agent with no agent name and no Signature-Agent header. Cloudflare Radar lists a muse- prefix for a Muse client, but those Muse browser requests did not use it.

Can you block Muse by IP address?

You cannot reliably block Muse by IP address. Observed Muse browser traffic came from a residential mobile network, and a teardown of Muse's browser stack found that Muse routes browser egress through residential exits near the person.

Why isn't SwiftShader alone enough to detect Muse?

SwiftShader alone is not enough to detect Muse because it is Chromium's CPU renderer. Chrome no longer falls back to SwiftShader automatically, but a flag or enterprise policy can still enable it for headless servers, managed VMs, and remote desktops. Use SwiftShader as one signal in a score.

Does arm plus Linux x86_64 mean the User-Agent is spoofed?

No. arm plus Linux x86_64 does not mean the User-Agent is spoofed. Since Chrome 107, User-Agent reduction freezes the Linux platform token to X11; Linux x86_64 on every CPU. The client hint is the real architecture. The combination means Chromium on ARM Linux, which includes Raspberry Pi users and ARM Linux VMs as well as Muse.

Should I deny Muse on every route?

No. You should not deny Muse on every route. Advanced Signals tells you that a browser agent submitted the request. Deny forms that are meant for people and point agents at your API or MCP server. Product pages and other routes need their own policy.

How do I enforce this with Arcjet?

To enforce Muse detection with Arcjet, add the Advanced Signals script to the pages that lead to the form, then call detectBot in the route handler. Requests that Signals denies report ARCJET_SIGNALS as the bot reason. Start in DRY_RUN to measure impact before LIVE.

Application security in your code

Protect your application with Arcjet

Classify the client inside the request handler, where the route, the user, and the business operation are all in scope.