Skip to content

Send DMs

The outreach pipeline sends templated DMs to crawled influencers via TikTok’s messaging system. It handles the full flow: search for the user, navigate to their profile, open messages, type the message, and send. 236+ DMs sent in production.

Terminal window
# Send DMs using strategy #1, targeting influencers with 10K+ followers
python3 -m marketing_system.bots.tiktok.outreach \
--strategy-id 1 \
--min-followers 10000 \
--delay 60 \
--limit 20
Terminal window
curl -X POST http://localhost:5055/api/bot/start \
-H "Content-Type: application/json" \
-d '{
"type": "outreach",
"device": "L9AIB7603188953",
"params": {
"strategy_id": 1,
"min_followers": 10000,
"max_followers": 500000,
"limit": 20,
"delay": 60
}
}'
from marketing_system.skills.tiktok import load
from marketing_system.bots.common.adb import Device
dev = Device()
skill = load()
wf = skill.get_workflow("send_dm", dev,
contact="@username", message="Hey! Love your content.")
result = wf.run()

For each targeted influencer, the bot performs this sequence:

  1. Search — type @handle in TikTok search
  2. Users tab — switch to Users tab in results
  3. Tap user — tap the matching user row
  4. Message button — tap “Message” on their profile
  5. Type message — type the strategy text with {{handle}} substitution
  6. Send — tap the send button
  7. Back out — navigate back to prepare for the next DM

Each DM takes approximately 30-45 seconds of device time.

Outreach messages are stored as templates in the outreach_strategies table. The {{handle}} placeholder is replaced with the influencer’s username at send time.

Terminal window
curl -X POST http://localhost:5055/api/strategies \
-H "Content-Type: application/json" \
-d '{
"name": "Free credits offer",
"message": "Hey {{handle}}! Love your content. We are offering free credits to try our platform. Interested?"
}'
Terminal window
# List all strategies
curl -s http://localhost:5055/api/strategies | python3 -m json.tool
# Update a strategy
curl -X PUT http://localhost:5055/api/strategies/1 \
-H "Content-Type: application/json" \
-d '{"message": "Updated message text..."}'
# Delete a strategy
curl -X DELETE http://localhost:5055/api/strategies/1

You can also manage strategies from the Strategies tab in the dashboard.

The outreach bot selects influencers from the database based on:

FilterCLI FlagDescription
Min followers--min-followersOnly contact influencers above this threshold
Max followers--max-followersSkip mega-influencers who won’t respond
Labels--labelTarget specific categories (cat, dog, pet)
StatusAutomaticOnly contacts not_contacted influencers
Custom query--querySQL WHERE clause for advanced filtering

Each influencer progresses through a status pipeline:

not_contacted -> dm_sent -> replied -> deal_closed
\-> rejected

Status updates happen automatically:

  • dm_sent — set immediately after successful send
  • replied — detected by inbox scanning
  • deal_closed / rejected — set manually via API or dashboard
Terminal window
# Manual status update
curl -X POST http://localhost:5055/api/outreach/42 \
-H "Content-Type: application/json" \
-d '{"status": "deal_closed", "notes": "Agreed to collab"}'

The bot uses randomized delays between DMs to avoid detection:

  • Default delay: 60 seconds
  • Actual delay: randomized between 45-75 seconds (random.uniform(0.75, 1.25) * delay)
  • Daily limit: configurable via --limit flag (default: no limit)

Use stealth mode for additional detection avoidance:

dev.stealth_tap(540, 1200) # Gaussian jitter on coordinates
dev.stealth_type("message") # Character-by-character with random delays

After sending DMs, scan the inbox to detect replies:

Terminal window
# Scan DM inbox
python3 -m marketing_system.bots.tiktok.inbox_scanner --max-scrolls 10

Or via the API:

Terminal window
curl -X POST http://localhost:5055/api/bot/start \
-H "Content-Type: application/json" \
-d '{"type": "inbox_scan", "device": "L9AIB7603188953", "params": {"max_scrolls": 10}}'

The scanner captures reply screenshots and updates influencer statuses in the database.

Set up recurring outreach via the scheduler:

Terminal window
curl -X POST http://localhost:5055/api/schedules \
-H "Content-Type: application/json" \
-d '{
"name": "Daily outreach",
"job_type": "outreach",
"device": "L9AIB7603188953",
"interval_minutes": 1440,
"params": {"strategy_id": 1, "min_followers": 10000, "limit": 15},
"max_duration_minutes": 30,
"priority": 3
}'
  • ASCII only — emoji and non-ASCII characters are stripped from messages. This is a limitation of adb shell input text.
  • One account per device — cannot send from multiple TikTok accounts simultaneously on the same phone
  • No read receipts — cannot detect if the DM was read, only if a reply was received