Proxy Toolbox
Proxy Toolbox / Guides / adspower-profiles

AdsPower proxy setup: profile fields, bulk import and the checks before first login

I keep 60 to 80 AdsPower profiles alive at any given time. The browser handles the fingerprint side of that work. The address side is mine, and for a long stretch I handled it badly.

One failure rewrote my whole procedure, and it was a quiet failure. A profile opened, the built in proxy check reported success, the account loaded, and four days later that account asked for a phone number. Going back through the profile I found WebRTC sitting on its default mode and a name lookup that had left over my own connection during the first page load. AdsPower had reported success because success, to that button, means the endpoint answered one request.

What follows is the procedure I use today, written as steps with a verification after each one. Every section ends with the thing I look at before moving on. The sequence matches a real setup: the fields in the profile card, the difference between a saved entry and a proxy bound to one profile, the row shapes that survive a bulk import, the built in test and its blind spots, the three checks before a first login, the layout of profiles across addresses, the local API, credential storage, and the errors that greet you at profile start. Endpoint shapes and numbers come from profiles running on my own machines while I write this.

The proxy fields in the profile card, field by field

A new profile opens with two blocks: fingerprint on one side, proxy on the other. The proxy block holds six fields on the versions I run, and each one changes something downstream.

The first field decides where the entry comes from. AdsPower accepts a line typed by hand, an entry picked out of proxy management, or a pull from an integration tied to a provider account. My habit is to type the first profile of a batch by hand and save that entry only after it survives the checks further down.

Type comes next: HTTP, HTTPS, SOCKS5, or none. This field does more than label the row. It decides which transport Chromium negotiates on start, and it decides whether the credential pair is offered at all.

Host and port are the two fields nobody fills in wrong. Account and password are the two that break in silence, because a trailing space pasted out of a spreadsheet cell travels straight into the authentication attempt and nothing in the interface shows it to you.

The last field is the IP checker. AdsPower fires one request through the endpoint at a lookup service, then uses the answer to fill timezone, language and location hints on the fingerprint side. Two services can disagree about the same address by a whole zone, which is why this field belongs to setup work.

FieldWhat AdsPower does with itWhat I look at before saving
Proxy sourcereads a typed line, a saved entry, or a provider pullsaved entries carry an edit history, typed lines do not
Proxy typepicks the transport and decides if credentials are sentSOCKS5 with a login pair needs the type set before the pair is stored
Hostthe address Chromium dialsno scheme in this box, the type field owns that
Portthe listening port on that addressHTTP and SOCKS5 ports differ on the same machine
Accountusername sent on the proxy challengetrailing space, and a capital letter the panel did not send
Passwordsecret sent on the same challengepasted from the panel, never retyped from a screenshot
IP checkerone lookup that fills timezone and languagethe zone it returns has to match what I set on the fingerprint tab

Verification for this step is small and takes ten seconds: save the profile, reopen the card, and read the six fields back. AdsPower normalises some input on save, and reading it back is how you catch a port that landed in the host box or a type that reverted to HTTP.

The shared proxy list and a proxy bound to one profile

AdsPower gives you two places to keep an endpoint, and mixing them up is the most expensive mistake in this whole article.

Proxy management holds saved entries. A profile that points at a saved entry holds a reference, so editing the entry once moves every profile attached to it. That behaviour is a gift when a package rotates its credential pair, and it is a hazard when 40 accounts share one line and that line stops answering. Every one of those 40 profiles goes down together.

A proxy typed into the card belongs to that profile alone. Nothing else moves when you edit it. Nothing else breaks when it dies. The cost is transcription: 40 profiles means 40 edits when something changes.

My split runs along the value of the account inside the profile. Accounts that took weeks to warm up get their own bound line, typed into the card, never shared. Throwaway profiles for reading public pages sit in groups of four on a shared saved entry, because losing four of those at once costs me a coffee break. Pairing endpoints with profiles this way is the part most guides skip, and it matters more than any fingerprint slider; my longer notes on proxy endpoints for antidetect profiles cover the same split from the endpoint side.

There is a third state worth naming. A profile set to "no proxy" opens on your own connection with a full fake fingerprint on top. That combination is the loudest signal you can send, because the fingerprint says one machine and the address says another. I keep a group named LOCAL for the two profiles allowed to do that, and no account ever logs in from that group.

To verify the split, open proxy management and sort by usage count. Any saved entry attached to more than four profiles gets a second look from me, and any entry attached to a profile holding a warmed account gets converted to a bound line on the spot.

Row formats when profiles arrive from a spreadsheet

Bulk import is where most people meet AdsPower's proxy parser, and the parser is stricter than the interface. The import template carries either split columns for the four proxy parts or a single column holding the whole string, and different template versions favour different shapes.

Split columns are the shape I trust. Four cells, four values, no parsing involved: type, host, port, account, password. When a spreadsheet arrives from someone else with everything mashed into one cell, I split it in the sheet before the import runs with a formula, because hand splitting 200 rows produces at least one error every time.

Here is how the shapes I have fed it actually land.

String in the cellHow the importer reads itResult
45.153.14.62:8000host and port, no credential pairopens where the machine address is bound in the panel
45.153.14.62:8000:u17402:k93qmzfour parts split on colonsmaps to host, port, account, password
http://45.153.14.62:8000scheme plus host and portscheme fills the type column, credentials stay empty
socks5://45.153.14.62:1080scheme sets SOCKS5 transportworks, and the type column can be left blank
u17402:k93qmz@45.153.14.62:8000userinfo ahead of the hostaccepted by some builds, dropped in silence by others
http://u17402:k93qmz@45.153.14.62:8000full URI formthe shape I use when one column has to carry everything
45.153.14.62 8000 u17402 k93qmzspaces where colons belongthe row imports with a broken host and no warning

The dashboard I pull from hands out lists in exactly two shapes, IP:PORT and IP:PORT:LOGIN:PASS, by link or by file, which lines up with rows two and one in that table with no editing at all. For a batch of 50 profiles I paste the list into a column, run a split formula, and the import goes through untouched. Those SOCKS5 lines exported straight from the panel drop into the template as four columns, and the only cell I add by hand is the type.

One warning about the type column. Some template versions want a word, some want a number, and a mismatch there imports every row as HTTP without a single complaint. After any import I sort the profile list by proxy type and count the rows. If I imported 50 SOCKS5 lines and see 50 HTTP profiles, the type column mapping was wrong and the whole batch gets deleted and redone.

Verification after an import is a count and a spot check: profile count matches row count, then open three random profiles from the middle of the batch and read their proxy cards. Errors from a bad parse cluster, so three samples find them.

The built in connection test, and the parts it leaves out

Every proxy card has a check button. Press it and AdsPower opens a connection through the endpoint to a lookup service, then reports the address it saw, along with country, timezone and language hints. Green text, a few numbers, done.

That test answers exactly one question: did this endpoint accept a connection and pass one request through, at this second. Everything else people read into the green text is imagination.

Here is what the button does not touch. It says nothing about WebRTC, because WebRTC lives in the browser profile and the check runs outside it. It says nothing about where name lookups will go once the profile opens, because a single lookup through the endpoint proves nothing about the resolver Chromium picks later. It says nothing about stability, because one request finishing in 400 ms tells you nothing about a session held for 40 minutes. It says nothing about concurrency, since it opens one socket while your real work opens 30. And it says nothing about agreement between the address and the fingerprint you set on the other tab.

I still press it, for one reason. A red result means the line is wrong or the endpoint is down, and catching that in the card saves a profile start. Treat it as a syntax check on your typing.

The rest belongs to the next step, run inside the profile itself, where the browser stack is the thing being measured.

Three checks before the first login

This is the step my early setup skipped, and the one that cost me the account I described at the top. The profile opens, and before any login form gets touched, three things get proven from inside the browser.

Exit address. Open an echo page in the profile and read the address back. It has to match the host in the proxy card exactly. A mismatch here on a bound package usually means the profile fell back to your own connection during start, which some builds do when the endpoint refuses the first connection.

Name resolution. Load a resolver test page and read which servers answered. Resolvers that belong to your own provider mean the lookup left over your connection while the traffic went through the endpoint, and that split is visible to anything watching timing. With an HTTP endpoint, Chromium sends the hostname inside CONNECT and the proxy resolves it. With SOCKS5 the behaviour varies by build, so I test it every time and treat assumptions as unproven.

WebRTC. The profile's fingerprint tab carries a WebRTC mode, and the mode has to be the one that replaces candidates with the proxy address. Real mode publishes your actual address to any page that asks, through a channel that has nothing to do with the proxy. Disabled mode hides the address and also marks the profile as unusual, since almost no real browser has WebRTC switched off. Replaced is the mode I want, and I verify it with a snippet in the profile's own console.

const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
});
pc.createDataChannel('probe');
pc.onicecandidate = (e) => {
  if (e.candidate) console.log(e.candidate.candidate);
};
pc.createOffer().then((o) => pc.setLocalDescription(o));

Any candidate line carrying a public address that differs from the proxy host means the mode is wrong. Private ranges like 192.168.x.x in the candidate list are normal and harmless.

CheckWhere I run itPass conditionWhat a failure means
Exit addressecho page inside the profilematches the host in the proxy cardfallback to the local connection at start
Name resolutionresolver test page inside the profileanswering servers sit behind the endpointlookups escaping the tunnel
WebRTCprofile console, snippet abovecandidates carry the proxy address onlyfingerprint tab set to real mode
Timezoneecho page, compared to the fingerprint tabsame zone on both sidesIP checker disagreed with your manual setting

An endpoint that keeps the origin address out of every one of those four rows is doing the job I bought it for, and anonymous endpoints that hide the origin address are the ones I keep for profiles holding real accounts. Four rows, two minutes, one profile. For a batch of 50, I run all four on three profiles and accept the batch if all three pass, because they share one pool and one build.

Laying profiles out across addresses

Once the checks pass, the question turns into arithmetic: how many profiles per endpoint, and how many endpoints per package.

My package gives 1000 threads on the standard tier and up to 3000 on the corporate one, and packages do not stack; buying a second one adds a second pool of threads with its own ceiling. There is one detail that catches people sizing a fleet. A package carries 2 bound addresses, and with both in use the thread ceiling splits between them. Size against 500 whenever two machines are bound at once.

A browser profile is light on threads and heavy on time. One AdsPower profile browsing normally holds 6 to 20 sockets open, spiking during page load and dropping to near zero while a human reads. Against a 500 thread half that gives room for far more profiles than one machine can render, so threads stop being my limit long before RAM does. On a 32 GB box I run 12 profiles at once comfortably and 18 with the fans audible.

The layout that survived contact with reality looks like this. Accounts that matter get one endpoint each, held for the life of the account. Profiles doing read only work share endpoints four to one. Fresh profiles being warmed up get an endpoint from the pool and keep it for the first two weeks, since an account that changes address on day three of its life gets asked for verification more often than one that stays put.

The pool behind my lines runs around 12000 active entries with rotation happening automatically inside it, so a fresh line for a new profile is always a click away in the panel. Access is sold by term with no cap on transfer, which is what makes long browser sessions workable: a profile can sit open all afternoon streaming media in a tab and nothing meters it. For steady account work I keep access booked for the whole month running so the endpoint list under my profiles stays stable, and the endpoints I assign to profile groups come off private hardware, the same way proxy groups work in Dolphin Anty, which is why sessions hold long enough for the layout above to mean anything.

Verification here lives in a spreadsheet. One row per profile, columns for endpoint, group, account, date bound, last check. When a profile misbehaves I sort by endpoint, and twice that sort has shown me three failing profiles sharing one line that had gone bad, which turned a mystery into a single edit.

Driving AdsPower from the local API

Everything above is clickable. At 50 profiles clicking stops scaling, and the local API takes over.

AdsPower exposes an HTTP interface on the machine itself, at local.adspower.net:50325 by default, and the client has to be running for it to answer. First call in any script of mine checks that the client is up.

curl "http://local.adspower.net:50325/status"
-> {"code":0,"data":{},"msg":"success"}

Profile creation carries the proxy inside user_proxy_config. Custom endpoints go in with proxy_soft set to the generic value, since the named values belong to provider integrations.

curl -X POST "http://local.adspower.net:50325/api/v1/user/create" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "batch-c-014",
    "group_id": "1937",
    "user_proxy_config": {
      "proxy_soft": "other",
      "proxy_type": "socks5",
      "proxy_host": "45.153.14.62",
      "proxy_port": "1080",
      "proxy_user": "u17402",
      "proxy_password": "k93qmz"
    },
    "fingerprint_config": {
      "webrtc": "proxy",
      "language": ["en-US", "en"],
      "flash": "block"
    }
  }'

The webrtc key set to the proxy value is the same setting I described two sections up, and setting it at creation time removes the manual step from every profile in the batch. That single line is the highest value thing in this whole request body.

Starting a profile returns the ports an automation library needs.

curl "http://local.adspower.net:50325/api/v1/browser/start?user_id=k11ozz8&ip_tab=1&open_tabs=1"
{
  "code": 0,
  "data": {
    "ws": {
      "puppeteer": "ws://127.0.0.1:52341/devtools/browser/9f2c...",
      "selenium": "127.0.0.1:52341"
    },
    "debug_port": "52341",
    "webdriver": "C:\\...\\chromedriver.exe"
  },
  "msg": "success"
}

With ip_tab=1 the profile opens its own address check tab on start, which turns my exit address verification into something that happens on every launch with no extra work. From there a script attaches over the returned socket.

const puppeteer = require('puppeteer-core');

const res = await fetch(
  'http://local.adspower.net:50325/api/v1/browser/start?user_id=k11ozz8'
).then((r) => r.json());

const browser = await puppeteer.connect({
  browserWSEndpoint: res.data.ws.puppeteer,
  defaultViewport: null,
});

const page = (await browser.pages())[0];
await page.goto('https://target.example/account', { waitUntil: 'networkidle2' });

Two operational notes from running this at volume. The local interface accepts roughly one request per second, and a loop that fires faster comes back with a frequency error that looks like a bug in your code. I put a one second gap between calls and the errors went away. Second, always call the stop endpoint when a job finishes, because a profile left running holds its sockets and the next start on the same profile fails with a lock message.

curl "http://local.adspower.net:50325/api/v1/browser/stop?user_id=k11ozz8"
curl "http://local.adspower.net:50325/api/v1/browser/active?user_id=k11ozz8"

The active call is my verification for this whole step. After a batch run I loop it over every profile in the batch, and anything still reporting as active gets stopped by hand before the next run starts.

Where the login and password pairs live

Two credential pairs live in every profile: the proxy pair and the account pair. Both get stored inside AdsPower, and both deserve a policy.

Proxy pairs go into a saved entry when the endpoint is shared and into the card when it is bound. My source of truth for those pairs sits outside AdsPower, in a plain file exported from the panel, because a machine failure that takes the client with it should never take my endpoint list too. Restoring 60 profiles from a template plus a list takes an hour. Reconstructing an endpoint list from memory takes a week.

Account pairs go into the profile's account fields, which also hold a slot for a two factor secret. Storing the second factor next to the password in the same profile makes the second factor decorative for anyone who reaches the machine, so mine live in a separate manager and I paste the code at login. That costs me four seconds per login and removes a whole category of bad day.

One habit that pays off during a credential rotation. Name saved entries after their purpose, never after their address. An entry called warmup-pool-03 survives a host change with one edit. An entry called 45.153.14.62 becomes a lie the moment the line changes, and six months later nobody remembers which profiles it belongs to.

To verify the storage side, export the profile list from the client every week and diff it against last week's file. Profiles that changed endpoints show up as two changed columns, and if I did not make that change, something else did.

Errors at profile start, line by line

A profile that refuses to open produces a short message, and each message points somewhere specific. These are the ones I meet most.

Message at startWhat it points atWhat I do
proxy connection failedendpoint refused the socket, or host and port are wrongretype host and port, then test the same line in another tool
ERR_TUNNEL_CONNECTION_FAILEDCONNECT never completed, usually a rejected credential paircheck for a trailing space in the account field
ERR_PROXY_CONNECTION_FAILEDendpoint is unreachable on both schemestake a fresh line from the panel, the machine is out of the mix
ERR_NAME_NOT_RESOLVEDa hostname went to a resolver that has no answerproves lookups are escaping the tunnel, fix the transport first
ERR_EMPTY_RESPONSEconnection opened, then closed with nothing sentwrong transport, SOCKS5 endpoint addressed as HTTP
IP check failedlookup service unreachable through the endpointusually the service, retry once before touching the profile
profile stuck on openingbrowser core still downloading, or a previous session holding a lockstop the profile through the API, then start again
local API frequency errorcalls fired faster than one per secondadd a gap, the limit counts calls across the whole client
port 50325 in usea second client instance, or a stale processclose both, confirm the port is free, start once

Two of those rows deserve a sentence more. The difference between a tunnel error and a proxy connection error is the fastest diagnostic in the list: a tunnel failure means the endpoint answered and refused you, and a proxy connection failure means nothing answered at all. The first is a credential problem on a live machine. The second is a dead line, and no amount of retyping fixes it.

The other row is the frequency error, because it looks like a code bug and reads like a server problem. Both readings miss it. The client throttles the local interface, the throttle counts calls across every profile at once, and a batch loop with no pause hits it on the third profile every time.

When a whole group starts failing at once, I go to the endpoint before I go to the profiles. Sort the tracking sheet by endpoint, find the shared line, take a fresh one from the panel, edit the saved entry once, and the group comes back together. That workflow only exists because of the split I described early on, which is the argument for spending ten minutes on how endpoints pair with antidetect browsers before spending a week on fingerprint settings that were never the problem.

If the same endpoints have to work outside AdsPower as well, the neighbouring guides pick up where this one stops: routing a normal Chrome install through the same lines is covered in the SwitchyOmega setup guide, sending desktop software that holds no proxy field of its own is covered in the Proxifier walkthrough for Windows, and attaching credentials in a headless script is covered in the Puppeteer proxy authentication guide. When a panel line has to become the exact string a template column or an API body expects, the connection string builder does the conversion between the four part form, the URI form and the split field form without the transcription errors that come from doing it in a spreadsheet at midnight.