ARMANOS

Solutions

Ad accounts

Each ad account gets its own browser: its own directory on disk, its own derived device, its own proxy. The point is not invisibility. The point is that a decision about one account stays a decision about one account.
40 a day
The ad scenario's page ceiling at full pace, reached on day seven of the warm-up ramp
4 consoles
Google Ads, Meta Ads, TikTok Ads and Microsoft Ads, each with rules written per host
56 rules
What an ad profile loads: 31 general tracker rules plus 25 written for the consoles
1 a day
Payment edits the scenario treats as a safe day, its most conservative ceiling

A ban should stop at the account it hit

Losing one ad account is a cost of doing business. Losing five because one of them was reviewed is a different problem, and it is usually not about the ban at all. It is about what the platform can see those five accounts have in common.

Open two consoles in one browser and they share everything that matters: the cookie jar, local storage, service workers, saved cards, one exit address and one set of device readings. A reviewer looking at one account has the rest one query away. An incognito window does not fix this. Incognito forgets at the end of the session, it does not give the second account a different computer.

ARMANOS gives each ad account a browser of its own. Nothing crosses between two profiles unless you put it there. The rest of this page is which link is cut, how, and in which file.

What this is not is a way around review. Platforms suspend accounts over spend patterns, creatives, landing pages, complaints and account age, and none of that is a browser question. Isolation buys one thing, and it is worth buying: the blast radius of a ban is one profile.

  • One cookie jar

    The console's own login cookie is the shortest link there is, and every window of that browser can see it.

  • One storage

    localStorage, IndexedDB and service workers persist per browser profile, and ad platforms write identifiers into all three.

  • One device

    Screen, cores, memory, GPU strings, fonts, timezone and language are identical in every window of the same browser.

  • One exit address

    Two consoles reached from the same IP minutes apart are related without anyone having to look hard.

  • One payment identity

    A saved card, an autofilled billing address and the browser's own payment profile follow the browser, not the account.

Choosing the ad scenario writes five decisions into the profile

The scenario is a record in the code, not a label on a card. Picking Ad accounts when you create a profile sets the page it opens, the tracker lists it loads, whether links are cleaned, which page scripts are installed, and the daily ceilings the app shows next to that profile.

Two of those change what leaves the browser. The tracker lists are compiled into a small extension the app writes into the profile directory before launch, so blocking happens as network rules and not as a script a page could read back. Link cleaning strips 40 tracking parameters on navigation, and the click identifiers of every console the scenario covers are in that list: gclid, wbraid, gbraid, msclkid, fbclid and ttclid among them.

One of them changes nothing about the browser at all. The action ceilings are numbers the app puts on screen. That difference is kept explicit further down this page, because a ceiling nobody enforces is still useful and is not worth lying about.

The record below is read out of the code, not written for this website. The app reads the same lines when it launches the profile and again when it draws the card.

scenario id
ads
start page
https://ads.google.com
tracker lists
general + ads, 56 rules
page scripts
fingerprint, stealth
link cleaning
on, 40 parameters
daily page ceiling
40, warm-up over 7 days
action ceilings
5: campaign edits, budget changes, new campaigns, payment edits, account switches
consoles
Google Ads, Meta Ads, TikTok Ads, Microsoft Ads

SCENARIOS.ads in packages/shared/src/index.js.

The rules name their host, because the console has to keep working

A blocklist built for privacy browsing is the wrong instrument inside an ad console. Cut one request too many and you cannot upload a creative, open a billing page or load a report, and the profile is useless for the work it exists for.

So the ad rule set is written the other way round. It contains no bare path rules at all: every entry names the host it belongs to, which is why a rule meant for one console cannot fire on a client's landing page. Requests a console needs in order to sign in, load, upload creatives, bill or answer its own API are excluded on purpose, and so is every host that answers a top-level navigation.

What is left is cross-account correlation: conversion and audience pixels, the signal endpoints, the third parties that sell the join. Twenty-five rules across the four consoles and the identity graph, on top of the 31 general rules every ARMANOS profile loads whatever its scenario.

Two rules are first-party, meaning they match requests a console makes to itself. Both carry their own host inside the rule, so neither can travel to another site.

ConsoleRules in the ad listWhat they match
Google Ads8, plus 4 first-partyConversion and audience pixels, tag services, and the console's own gen_204, jserror and csi beacons
Meta Ads4, plus 1 first-partyThe signals script, fbevents.js, the tr pixel, and the ajax/bz logging call on facebook.com
TikTok Ads2Both analytics hosts, including the Singapore one
Microsoft Ads4The Bing click and log endpoints and the MSN event host
Any site7 third-partyThe identity graph: adsrvr, demdex, rlcdn, agkn, crwdcntrl, scorecardresearch, everesttech

Blocking is not the feature here, and it is not sold as one

The lists are narrow on purpose. An ad profile is bought for isolation; the tracker rules exist so that one account's browsing does not become a signal about another, not to make you unmeasurable.

The card and the login live inside the profile, not on your machine

A saved card, a billing address and an autofilled name are browser data. They live in the Chromium profile directory, and every ARMANOS profile has one of its own: the engine is launched with a user data directory pointing at fork-profiles and the profile's id. Cookies, local storage, service workers, saved cards and autofill are inside it. Two ad accounts are two directories.

The engine is also kept out of the machine's credential store. It runs with a mock keychain and a basic password store, so it encrypts its own cookie and password database instead of asking macOS, Windows or Linux for the key. That was measured, not assumed: without those flags a launch on macOS made zero requests and sat on a keychain prompt no password could satisfy. It also keeps the profile portable, which is what makes moving a live session to another machine possible at all.

The account's own login pair is held by the app rather than by the browser: sealed through the operating system's keychain and written beside the profile with owner-only permissions. It is never sent to our server. When the desktop syncs a profile, the request carries the id, the name, the folder, the scenario, the fingerprint template, the proxy and a couple of labels. There is no field in it for an account password. The one-time code sits in the same place: the 2FA secret belongs to the profile and stays on that machine.

The proxy password is handled the same way for a different reason. It is never placed on the command line, because a credential in an argument shows up in any process listing on the machine, and because the credentialled form was measured to load nothing at all on this engine. The browser is pointed at a loopback bridge that holds the credential and answers for it.

  • The profile directory

    fork-profiles and the profile id, under the app's data folder: cookies, storage, service workers, saved cards, autofill.

  • The account password

    Sealed by the OS keychain, owner-only file permissions, never uploaded to us.

  • The one-time code

    The TOTP secret belongs to the profile, and the app generates the code beside the profile it belongs to.

  • The proxy password

    Sealed at rest, and the proxy list reports only that a password is set. Taking the working credential is written to the log.

  • The payment edit ceiling

    One a day, warning at 99 percent of it. Changing the card on three accounts in an hour is itself a pattern.

The device the console sees belongs to the profile, not to your laptop

The fingerprint is not stored anywhere. It is derived at every launch from four inputs: the template you picked, the profile's id, the country the proxy exits in and the engine's own version. The same four inputs always produce the same machine, so an account never finds its computer changed overnight.

That is what makes a shared profile usable in an agency. The id travels with the profile, so when a media buyer opens it on their own laptop, the readings are the ones the account saw yesterday. Their real screen, cores, memory and GPU do not leak into it. The comment on the sync path in the desktop app puts it in five words: the same identifier is the same machine.

Geography is measured rather than typed. Before the first launch the app asks up to four providers over HTTPS, through the profile's own proxy, where that proxy comes out, and the country decides the timezone and the language stack. Change the proxy to a different exit and the stored country is cleared, so the next launch measures again instead of showing a German address with Kyiv time.

The substitution happens in the engine. ARMANOS Browser 153.0.7978.0 is our own Chromium build, and the readings reach it as a seed on the command line rather than as a script patching the page. Generation 4 of the generator, five templates, 25 readings you can compare against your own browser on the fingerprint tool.

  • Template

    One of five: macos-chrome, windows-chrome, linux-chrome, android-chrome, android-tablet.

  • Profile id

    Seeds the GPU pair, the screen, the user agent and the platform version out of generation 4's pools.

  • Proxy country

    Measured through the proxy itself, then mapped to a timezone and a language stack that agree with it.

  • Engine version

    153.0.7978.0 is claimed in the user agent and in every client hint, because it is the engine actually rendering the page.

WebRTC is not offered a way around the proxy

The engine launches with its WebRTC IP handling policy set to disable non-proxied UDP, so the browser does not volunteer a direct route while the page is loading through the proxy.

A media buyer sees one client's folder and nothing else

An agency does not want a new buyer to see every client. A role cannot do that on its own, because a role covers the whole workspace: an operator sees every profile shared with them. Folder access is the part that narrows it. You choose which folders a member may see, and the server keeps one row per member per folder.

Three details turn that into a boundary instead of a filter on a list. A profile that is in no folder is not shown at all once access is set, so the restriction cannot be dodged by leaving a profile out of a folder. Opening a profile straight by its id is checked by the same rule and answers profile not found rather than forbidden, so the difference between the two answers cannot be used to map what the workspace holds. And the restriction is recorded against the workspace owner, so it does not follow a person to their next employer and lock them out there.

An empty list means the member sees everything. That is a deliberate choice. If no rows meant no access, the day the feature shipped would have locked out every existing team, and taking a member's last folder away would silently have meant taking away all of their access.

Access does not carry passwords with it. The proxy list never returns a password, only whether one is set; the working credential comes from a single endpoint and taking it is written to the log. The account password was never on the server to begin with. Handing out folder access is logged too, with who did it and which folders.

  • Owner

    Everything, and cannot be removed from their own workspace or restricted to folders.

  • Admin

    Billing, the team, the log, other members' profiles and machines. Hands out folder access.

  • Manager

    Shared working resources: folders and the proxy pool, including rotating a mobile proxy. No money, no team.

  • Operator and member

    Work with the profiles they were given, inside the folders they can see. Change nothing shared.

  • Seats

    Business includes 3, Enterprise 20, and additional seats are 3 dollars a month each.

The Groups screen in ARMANOS listing the folders Marketplaces, Social media, Ad accounts and Clients
Folders are shared across the workspace. Access is then handed out folder by folder, member by member.

Two people cannot open one ad account at once

A running profile holds a lock for three minutes at a time, renewed while it runs. A second machine is refused and told who is holding it. A machine that is switched off releases the profile when its lock expires.

What the ceilings count, and what they only suggest

An ad profile carries five action ceilings and one page counter. The page counter is the only number the app measures. It counts top-level navigations in that profile's windows, keeps them in a small file so a relaunch on the same day does not reset the count, and starts fresh at midnight. At full pace it is 40 a day.

New profiles ramp. The first seven days multiply the ceiling by 0.2, 0.35, 0.5, 0.65, 0.8, 0.9 and 1.0, so an ad profile shows 8 on day one and reaches 40 on day seven. The bar turns amber at 80 percent of the day's ceiling and red at it. It never blocks anything, and the app does not pretend otherwise.

The five action ceilings are numbers, not counters. The app cannot see that you edited a campaign inside a console, so it shows what the scenario treats as a safe day, ramped by the same curve. Payment edits are the strictest of them, one a day with the warning at 99 percent, because a payment change is the event most likely to put a human reviewer in front of the account.

One caveat is built into the wording on screen. The day count is the age of the ARMANOS profile, not the age of the ad account behind it. The app has no way to know the second one, and the label was corrected once it was noticed that it had claimed to.

What the scenario counts as a dayFull ceilingDay one of the rampWarning at
Campaign edits12270 percent
Budget changes4150 percent
New campaigns3167 percent
Payment edits1199 percent
Account switches3167 percent
Pages opened (measured)40880 percent
The ARMANOS profile list, each card showing a safe pace bar, the warm-up day and a list of per-action daily ceilings
The pace bar and the ceiling block, as they appear on a profile card. These cards are e-commerce profiles; an ad profile shows the same block with its own five rows.

When an account goes anyway

Some will. What matters then is how much goes with it. In one shared browser the honest answer is often the neighbours as well. Here the loss is bounded by a directory: the banned account's cookies and storage sit in that one profile and touch nothing else, and every other profile keeps working through the ban and the appeal.

Most of the setup is still yours. The proxy stays in the shared pool with its measured exit country. The folder and its access rules stay. The scenario and its ceilings stay. The profile itself stays until you decide otherwise, with its launches in the log: who opened it, from which machine, and when.

A replacement is a copy. Cloning carries the scenario, the fingerprint template, the folder, the tags, the notes, the start page, the enabled extensions, the proxy (by reference to the pool when it came from there) and the measured exit country, because that last one is a measurement of the same proxy rather than a secret.

A copy deliberately does not carry three things: the account's login pair, its one-time code secret, and its fingerprint. The first two belong to an account that is gone, and putting them into a second profile is how you eventually sign in as the wrong account from the wrong address. The third is not copyable by design. A clone is a new profile with a new id, and the fingerprint is derived from the id, so the copy is a different machine. Two profiles wearing one fingerprint would be tied together more tightly than anything else in this product could tie them.

Deleting is two steps. The profile goes to the recycle bin and can be restored, or it is purged. Purging closes the running browser first, then erases the directory, then clears the profile out of the launch notifications, the blocked-request counters and the pace counter, because a browser of this kind that keeps a launch history of profiles you deleted is keeping exactly the wrong thing.

  1. 1

    Clone the profile

    Settings, folder, proxy, measured country, extensions and start page come with it. The login pair, the 2FA secret and the fingerprint do not.

  2. 2

    Give it a different exit

    Another proxy from the pool, or a rotation on a mobile one. Changing the exit clears the stored country, so the next launch measures the new one and sets the timezone from it.

  3. 3

    Register the new account inside it

    The console meets an empty cookie jar, an address that account has never used, and a device it has never seen.

  4. 4

    Purge the old profile when the appeal is over

    The recycle bin holds it as long as you want. Purging erases the directory and every counter that referenced it.

The proxy is a decision, not a leftover

Pointing a replacement account at the exit address the lost one used is a link you are choosing to make. If the account mattered, give the replacement a different exit.

What this does not do

  • It does not prevent bans. Spend patterns, creatives, landing pages, complaints and account age are all reviewed, and none of them is a browser question.
  • It does not hide your IP by itself. Without a proxy the profile goes out from your own address, and the app says so in its first-steps list.
  • It does not count what you do inside a console. Only pages opened in the profile are measured; the five action ceilings are guidance you follow yourself, and nothing is ever blocked.
  • It does not create or warm up ad accounts. The warm-up ramp is a number on a bar, not activity on your behalf.
  • It does not know how old an ad account is. The day counter is the age of the ARMANOS profile, which is all the app can honestly see.
  • The engine work is not finished. A few readings are still corrected from the page rather than in C++; the remaining list lives in our sources and is closed build by build.

How to check

Every claim above is one file away. These are the lines that hold it and the stands that break if it stops being true.

The ad scenario is one record, and the app shows exactly its numbers
packages/shared/src/index.js (SCENARIOS.ads) · apps/desktop/src/main/main.js (actionLimitsFor, paceInfoFor)
Ad rules name their host, so nothing fires outside the console it was written for
apps/desktop/assets/trackers_ads.json · apps/desktop/src/lib/tracker-rules.js (TELEMETRY_BY_SCENARIO)
Each profile is its own directory, and the proxy password never reaches the command line
apps/desktop/src/lib/forkEngine.js (profileDir, proxyArg) · apps/desktop/test/proxy-auth-bridge.js
The account password and the one-time code secret stay on your machine
apps/desktop/src/lib/profiles.js · apps/desktop/test/login-in-keychain.js · apps/desktop/test/login-stays-local.js
Folder access hides a profile even from a member who knows its id
apps/server/src/profiles/profiles.service.ts · apps/server/test/group-access.js
Two machines cannot hold the same ad profile at the same time
apps/server/src/profiles/profiles.service.ts (LOCK_TTL_MS) · apps/server/test/profile-lock.js

Start with one client and two profiles

The Free plan gives you two profiles for good, with no card. macOS 13 and newer on Apple Silicon or Intel, Windows 10 and 11 on 64-bit, Ubuntu 22.04 and newer on 64-bit.