Arc anti-cheat integration

Connect Arc to your backend, receive account enforcement callbacks, validate protected players, and launch your game through Arc.

POST

Revoke player access

Arc sends this callback when a protected client loses access. Your backend decides how enforcement works: invalidate authentication, remove the player from the game, or disable protected features.

/outgoing/v1/anticheat/private/revoke
{
  "id": "accountid"
}
HeaderValuePurpose
User-AgentArc/{version}Identifies the Arc service version sending the callback.
Content-Typeapplication/jsonThe callback body is JSON.
X-Arc-AuthYour configured API keyRequired. Reject the request unless this exactly matches your Arc API key.
POST

Ban a player

Arc sends this callback when a detection results in a ban. Persist the ban against the supplied account ID and prevent the account from creating or joining protected sessions.

/outgoing/v1/anticheat/private/ban
{
  "id": "accountid"
}
HeaderValuePurpose
User-AgentArc/{version}Identifies the Arc service version sending the callback.
Content-Typeapplication/jsonThe callback body is JSON.
X-Arc-AuthYour configured API keyRequired. Reject the request unless this exactly matches your Arc API key.

Verify callback authentication

Check the authentication header before reading or acting on the account ID. Return an unauthorized response when the key is missing or incorrect.

function verifyArcCallback(request: Request) {
  const receivedKey = request.headers.get("x-arc-auth");
  const expectedKey = process.env.ARC_API_KEY;

  if (!expectedKey || receivedKey !== expectedKey) {
    return new Response("Unauthorized", { status: 401 });
  }

  return null;
}

export async function handleRevoke(request: Request) {
  const rejected = verifyArcCallback(request);
  if (rejected) return rejected;

  const { id } = await request.json() as { id: string };
  await revokeGameAccess(id);
  return new Response(null, { status: 204 });
}

Check Arc status

Forward the player's Arc authentication and client headers to the public status endpoint. Perform this check when creating a matchmaking ticket and again during in-game authorization.

const arcAuth = c.req.header("x-arc-auth");
const arcClient = c.req.header("x-arc-client");

if (!arcAuth || !arcClient) {
  return c.json([], 404);
}

const resp = await fetch(
  "https://dev-anticheat-v1.arc-services.dev/router/v1/anticheat/public/status",
  {
    method: "GET",
    headers: {
      "X-Arc-Client": arcClient,
      "X-Arc-Auth": arcAuth,
    },
  },
);

if (!resp.ok) {
  return c.text("", resp.status);
}
MatchmakingReject the ticket before allocating a server when Arc does not report an active protected client.
Game serverRecheck during authentication so a player cannot bypass the launcher by reusing only a matchmaking response.

Implement player authentication

Configure authentication methods in the client's Authentication tab so Arc can verify player credentials against your server before the protected game session begins. Use your verification URL for login decisions and X-Arc-Auth for authenticating Arc callbacks.

Login verification

Return HTTP 200 with subject and displayName for valid credentials. Any other status rejects the login.

Callback protection

Validate X-Arc-Auth on every revoke and ban callback before applying account changes.

Launcher setup

Configure the authentication method first, then start Arc\Arc.exe with the game arguments your method expects. The argument names are configurable; the values below are examples only.

1. Configure authentication

In the Authentication tab, choose Exchange Code or Password, enter your HTTPS verification URL, set the priority, and map the launcher arguments to your game. See the authentication guide for the request and response contract.

2. Download and place Arc

The currently hosted executable is available at https://cloud.arc-services.dev/modules/anticheat/Arc.exe. Place Config.json in the same directory as Arc.exe.

GameBuild/
|-- Arc/
|   |-- Arc.exe
|   |-- Config.json
|   +-- Splash/
|       +-- Splash.png
+-- Game/
    +-- Binaries/
        +-- Win64/
            +-- GameClient.exe

3. Create Config.json

The executable path is relative to the game build containing the Arc directory. The splash path is optional and is resolved from the Arc executable directory.

{
  "ClientID": "your client id",
  "Executable": "Game\\Binaries\\Win64\\GameClient.exe",
  "Splash": "Splash\\Splash.png"
}

4. Start Arc with the configured arguments

import { spawn } from "node:child_process";
import path from "node:path";

const arcExecutable = path.join(buildPath, "Arc", "Arc.exe");
// Example only. Use the argument names configured for your method.
const authenticationArguments = [
  "-AUTH_LOGIN", username,
  "-AUTH_PASSWORD", password,
];

const arcProcess = spawn(
  arcExecutable,
  [
    ...gameArguments,
    ...authenticationArguments,
  ],
  {
    cwd: buildPath,
    windowsHide: true,
  },
);

Before you ship

  • Validate X-Arc-Auth on both callback routes.
  • Make ban and revoke operations idempotent.
  • Check status during matchmaking and game authentication.
  • Verify player credentials through your HTTPS endpoint.
  • Pass the configured authentication arguments.
  • Keep Arc.exe and Config.json together.
Review the TypeScript SDK guide