A cold-DM automation platform for X, built on Apify end to end, with our own browser extension handling the account connection. Thirteen weeks, fixed price, working product on your domain at the end of it.
The official X API charges $0.015 to send a single DM and $0.010 to check for a reply. It also no longer permits follow, like or quote-post writes on any self-serve tier, and X's published developer policy explicitly refuses applications for bulk outreach automation. Building on it means asking permission for a product they have already said they will not permit, then carrying a fully loaded cost of about $66 a month per customer for the privilege.
So we are not building on it. Xollo runs entirely on Apify, driving X the way a person's browser drives it. That removes the approval risk, removes the follow-and-like limitation, and drops the fully loaded cost to serve a customer from about $66 a month to about $16.
We use existing Apify actors wherever one does the job, which is almost everywhere. If a function has no good actor, we write a small one to fill the gap, rather than building the whole send stack from scratch. Less to build, less to maintain, and nothing hand-rolled that a store actor already does well.
The one thing this architecture needs is the customer's X session. So rather than sending people off to a random Chrome cookie-exporter extension and asking them to paste a raw token string into a text box, we build our own extension: Xollo Connect. One click, no copy and paste, session health monitored, expiry caught before it breaks a campaign. It is the difference between a product and a script.
| Decision | What most tools do | What Xollo does |
|---|---|---|
| Account connection | Tell the customer to install a third-party cookie exporter, find two cookie values in DevTools, and paste a raw string into a form. | Xollo Connect, our own extension. One click. The customer never sees a token. Session health and expiry are monitored and surfaced before a campaign breaks. |
| Automation actors | Depend on one community Apify actor with no fallback, so when it breaks the product breaks. | Use the existing store actors that already do each job, with a second actor configured as a fallback for every function. If a gap has no good actor, we write a small one to fill it. Nothing built that a store actor already does. |
| Account safety | Blast a fresh account at full volume on day one and watch it get locked. | Warm the account up first. A warm-up actor spends one to two weeks browsing, liking and following gradually to build the account's standing, then Xollo sends within a conservative fixed daily cap. No guessing, no probing for a hidden limit. |
New X accounts that immediately start sending cold DMs get locked. The fix is not to guess how far you can push a cold account, it is to not send from a cold account at all. So Xollo warms an account up before it sends anything.
A warm-up actor runs human-like activity for one to two weeks: scrolling, liking a few posts a day, following a handful of relevant accounts, the ordinary behaviour of a real new user. That builds the account's standing with X and raises the volume it can sustain. Only then does Xollo start sending, and it sends inside a conservative daily cap rather than trying to find the edge. Warm-up automation like this already exists on Apify, so this is configuration and orchestration, not new research. It also means we are not gambling the product on discovering an undocumented limit, which was the riskiest idea in the earlier plan.
A cold account sending cold DMs gets locked. Xollo spends the first week or two making the account look like a real, active user, which raises the ceiling before we ever use it. Then it sends well inside that raised limit. Slower to first DM, far less likely to lose the account.
This is the piece that turns a technically-working script into something a customer will actually pay for and stay subscribed to.
Every competitor in this space onboards the same clumsy way: install Cookie-Editor, log into X, export a headers string, paste it into a text box, and re-do the whole thing every few weeks when it silently expires. Half your support tickets will be about that flow, and a good share of your churn will be people who could not be bothered doing it again.
Xollo Connect replaces it entirely.
Google treats authentication credentials as a sensitive data category. An extension may collect them, but the Chrome Web Store's Limited Use policy restricts what you may then do with them, and a reviewer will cross-check the manifest against the privacy policy against the dashboard disclosures. Any mismatch is a rejection. So this choice is not only about security, it is about whether the extension gets published at all.
My recommendation is Option 2. It is the only one that gets you a sellable product and a defensible answer when a customer, a reviewer, or an acquirer asks what you do with their session. Whichever we pick, sessions are envelope-encrypted with a managed key, never logged, never in URL parameters, and deletable in one click. That is not a nice-to-have here, it is the difference between a bad week and a company-ending week.
Green is code we own. Orange is the hard engineering. Red is the part that holds credentials and therefore gets the most attention.
500 leads become 500 queued jobs, spread over days inside the safe daily cap, not fired all at once.
Is this account warmed up and inside today's conservative cap? Is the session valid? Are there credits?
Bio and recent posts go to Claude. Out comes a personalised opener the customer can pre-approve.
The send actor delivers it on the customer's session, spaced like a human. Deduct a credit.
Repeated failures mean pause the account, alert the customer, and hold the campaign rather than push into a lock.
The poller reads the inbox, tags sentiment, and can drop a booking link into the reply.
Listed precisely, so there is no argument in week eleven. Anything on the right is a change request at $95 an hour, agreed in writing before work starts.
Two things sit on the critical path: the extension, because the Chrome Web Store review is outside our control, and the warm-up plus send pipeline, because account safety is the product.
Why the extension is built early. Chrome Web Store review takes days and can take longer if a reviewer wants changes to the privacy disclosures, which is likely given we declare authentication data. We submit in week 5 so that a rejection and resubmission still lands well before launch. If we left it to week 11, a single review round could push the whole delivery.
Confirm the shortlisted store actors work: warm-up, send, engage, inbox. Warm a burner account for a few days and measure how the safe send cap improves. Measure how long a session survives. Draft the extension's data disclosures against Chrome's Limited Use policy. Then decide Option 1, 2 or 3.
Login, database, app shell. The encrypted session vault with managed key, one-click wipe, and no logging of credential material anywhere in the stack.
The full extension: one-click connect, multi-account, session health, expiry alerts, disconnect. Privacy policy written, data disclosures filled, submitted to the Chrome Web Store.
Scrape followers, repliers, keyword results and community members through Apify. CSV upload. Filterable lead table. Suppression list enforced everywhere.
Wire in the store actors for warm-up, send, engage and inbox, each with a fallback. Build the queue, dispatcher and the conservative daily-cap scheduler. Warm a real account for a few days, then run a governed campaign through it. This is the biggest block, and everything downstream depends on it.
Follow, like and quote-post as steps inside a sequence, running on the Engage actor, governed by the same pacing engine and failing soft.
Replies land in one inbox across accounts, tagged by sentiment. A booking link can be dropped into a reply and the resulting booking is tracked to the campaign. Analytics show reply rate, booking rate, and account health.
Stripe subscription plus DM credits. Credits deduct per send. Campaigns hard-stop at zero. Depends on the pricing decision below.
Deployed to your domain. Extension published. UAT bugs fixed. Code, actors and runbook handed over. Two weeks of post-handover bug fixing included.
Fixed price, not hourly. If the estimate is wrong that is my problem, as long as the scope does not move.
| Milestone | Weeks | Amount |
|---|---|---|
| M0 — Spike and session decision | 1 | $1,500 |
| M1 — Foundation and encrypted session vault | 2–3 | $2,000 |
| M2 — Xollo Connect extension, built and submitted | 3–5 | $2,500 |
| M3 — Lead sourcing and lead table | 5–7 | $2,000 |
| M4 — Warm-up, actor integration, queue and send pipeline | 7–9 | $4,000 |
| M5 — Follow, like and quote-post steps | 10 | $1,000 |
| M6 — Reply inbox, calendar booking, analytics | 11 | $2,000 |
| M7 — Stripe billing and credits | 12 | $1,000 |
| M8 — Hardening, UAT, deploy, handover | 13 | $500 |
| Total | 13 weeks | $16,500 |
What changed from the ten-week, $12,000 version. Three weeks and $4,500 were added for two reasons. The extension is a real product in its own right, not a wrapper, and it carries a Chrome Web Store review we do not control. And the account warm-up plus fallback-actor wiring is real work: integrating several store actors, configuring a backup for each, and building the warm-up-then-cap flow that keeps customer accounts alive. We use existing actors rather than building our own, which keeps that number from being higher.
| Service | During the build | Once live |
|---|---|---|
| Apify | $49/mo | $49–199/mo + usage |
| Chrome Web Store developer account | $5 one-off | $0 |
| Supabase | Free | $25/mo + usage |
| Vercel | Free | $20/mo + usage |
| Worker hosting | ~$10/mo | $10–40/mo |
| Anthropic or OpenAI | ~$20 | ~$0.40/customer/mo |
| Stripe | $0 | 2.9% + $0.30/charge |
| Resend | Free | $0–20/mo |
| Rough total | ~$130 | ~$110–300/mo fixed |
| Weekly call | 30 minutes, Monday. |
| Milestone demos | A working link at the end of every milestone. You sign off or you list changes. |
| Code ownership | Your GitHub org from day one. The Apify actors are published under your account, not mine. |
| Staging | A URL you can poke at any time. |
| Post-handover | Two weeks of bug fixing included. A bug means it does not do what the scope says. A new idea is a change request. |
| Change requests | $95/hour, agreed in writing before work starts. |
Cost to serve one customer for one month, sending 100 DMs a day, which is about 3,000 a month.
Compared like for like, the same customer costs about $66 a month on the official X API and about $16.66 here. Both numbers are fully loaded: sends, reply reads, infrastructure, Stripe, AI and scraping. The gap is almost entirely the send line, $45 of X API charges versus roughly $6 of Apify compute for the same 3,000 DMs. That is the entire reason this architecture exists, and it is what lets Xollo price at $79 with about an 80% margin instead of $99 with a 35% one.
Credits rather than a flat daily promise, for one practical reason: a freshly warmed account and a long-established one safely handle very different volumes. Selling credits that a customer spends at whatever rate their account can sustain is honest, and it still makes money, whereas promising a fixed "250 a day" to an account that should not send that many is a refund waiting to happen.
This architecture is faster, cheaper and more capable than the official-API route. It is not free of risk, and I would rather write the risks down than discover them with you in week nine.
If Xollo's database leaks, an attacker gets full control of every stored account, not just the ability to send spam. This is the single largest liability in the product. What we do: envelope encryption with a managed key, nothing credential-shaped ever written to a log, one-click wipe, and the hybrid session model in Section 02 so that customers who want to keep the key can. Cyber liability insurance is worth pricing before launch.
Session automation breaches X's terms and enforcement lands on the customer, not on you. A customer who loses a ten-year-old account will not be quiet about it. What we do: warm the account up before it sends, hold it to a conservative daily cap with human-like spacing, and auto-pause on repeated failure rather than pushing into a lock. Plus honest marketing that does not promise safety we cannot deliver.
We declare authentication data, which puts us under Google's Limited Use policy and guarantees close reviewer scrutiny. A first-pass rejection is a realistic outcome. What we do: build and submit in week 5, not week 12, so a rejection and resubmission still lands early. Privacy policy and dashboard disclosures written to match the manifest exactly, since mismatches are the most common rejection reason. Self-hosted install is the fallback if the store says no permanently.
The store actors drive X's private endpoints. X rotates them, and a given actor can break or be abandoned by its author. This will happen. What we do: every function has a second store actor configured as a fallback, we favour actors that re-resolve endpoints at runtime, and if a gap opens with no good actor we write a small one. Budget a retainer for repairs. There is no version of this architecture where that maintenance goes away.
Dropping the X API means there is no Plan B if the session route becomes unworkable. The official API could not replace it anyway, since it no longer permits follow or like and would quadruple the cost. What we do: name it honestly. This is a deliberate bet on one route. It is the right bet on the numbers, and it is still a bet.
They host actors like these today, so evidently they permit it. Policies change, and X could pressure them. What we do: the dispatcher is written against a generic actor interface, so swapping to a different provider, or to a small self-hosted actor, is a configuration change rather than a rebuild. That portability is the reason the dispatcher is a distinct layer.
GDPR treats a scraped profile as personal data. Australia's Spam Act 2003 covers electronic messages broadly. Automating a logged-in session against a platform's terms is also a weaker legal position than scraping public data. What we do: nothing, because this is outside the scope of a build engagement and outside my competence. Get a lawyer's view before launch. Nothing in this document is legal advice.
Option 1, 2 or 3 from Section 02. My recommendation is Option 2: local sending by default, server-side as an explicit opt-in. This decides the extension's architecture, its Chrome Web Store disclosures, and how much liability you carry. Everything in M1 and M2 depends on it.
Credits or a flat DM cap. These are two different builds, not two settings on one build. M7 builds whichever you pick. My recommendation is credits, because a warmed account and a freshly connected one safely sustain very different volumes, so a flat cap becomes a promise you cannot keep for everyone.
Needed on day one: an Apify account with a paid plan, a Chrome Web Store developer account (a one-off $5), a domain, and two or three real X accounts we are allowed to warm up and test against during the M0 spike. Without a test account the spike cannot run, and week one cannot start.
| How much does warm-up actually raise the safe send rate? | Nobody publishes a clean number. The M0 spike warms a real account and measures the before-and-after cap. It sets the conservative default and informs the tiers. |
| How long does a session survive under automated load? | Scraper listings claim several weeks. Under heavy use it may be far less, which changes how aggressively the extension needs to prompt for reconnection. |
| Will Chrome approve the extension first time? | Unknowable until submitted. Building it in week 5 is how we buy room to fail once. |