How To Build a Human-Like Outreach Automation System Using Puppeteer and AI For Any Platform

Shivang SinghShivang Singh
5 min read

Problem

Let’s face it—lead generation is a pain.
Whether you're trying to find clients for your freelance gigs, customers for your SaaS, or potential hires for your team, the process can quickly become a time-consuming black hole of manual effort, guesswork, and spiraling costs.

And worse? It doesn’t scale.

So, I decided to flip the script—what if you could build an AI-driven automation workflow that handles the entire process for you, from discovery to outreach?

From finding the right people on the right platform, to crafting a solid outreach message, to actually contacting them—all while mimicking real human behavior and bypassing anti-bot mechanisms like a stealth pro.

In this guide, I’ll show you exactly how I did that—and how you can too.

Steps/Roadmap for a successful platform automation

1. Login: Handling Captchas and Saving Sessions:

Login is one of the most protected areas on any platform, typically safeguarded by CAPTCHA or rate-limiting mechanisms. To bypass these:

🔸 CAPTCHA Solving Tools

You can integrate services that solve CAPTCHAs:

These services offer APIs that you can call with the CAPTCHA image or site key, and they return a token you can use to submit the form.

🔸 Saving Login Sessions

Instead of logging in every time, save the session so Puppeteer loads the browser with cookies and login state already intact.

A general example of launching the browser for

const puppeteer = require("puppeteer");
const axios = require("axios");

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    userDataDir: './user_data',
    args: ['--start-maximized']
  });

  const page = await browser.newPage();
  await page.goto("https://example.com/login", { waitUntil: "networkidle2" });

  // Check for CAPTCHA
  if (await page.$('.captcha-image')) {
    const image = await page.$eval('.captcha-image', el => el.src);
    const res = await axios.post('https://2captcha.com/in.php', {
      method: 'base64',
      key: 'YOUR_API_KEY',
      body: image, // you may need to convert src to base64
      json: 1
    });

    const id = res.data.request;
    let code;
    while (!code) {
      await new Promise(r => setTimeout(r, 5000));
      const check = await axios.get(`https://2captcha.com/res.php?key=YOUR_API_KEY&action=get&id=${id}&json=1`);
      if (check.data.status === 1) code = check.data.request;
    }

    await page.type('#captcha-input', code); // Adjust selector
  }

  // Do login if needed...
  // await page.type('#username', 'user');
  // await page.type('#password', 'pass');
  // await page.click('#login');

  console.log("Ready with session & captcha solved!");
})();

2. Homepage Detection

After login, ensure that the browser has landed on the homepage. You can either:

  • Detect based on the URL

  • Check for unique DOM elements on the homepage

Add some smart waits to simulate natural browsing behavior.

// Wait like a real human using Promise
await new Promise(resolve => setTimeout(resolve, 3000));

if (page.url().includes("/home")) {
  console.log("We're on the homepage!");
} else {
  // Alternatively use a selector check
  await page.waitForSelector(".homepage-banner");
}

3. Scraping with API Interception (Not Just DOM!)

Instead of scraping complex and messy HTML, it's much easier and more reliable to intercept the API requests that the website uses to load its data.

To do this, open Chrome DevTools, go to the Network tab, filter by Fetch/XHR, and look for the API calls the site makes. Once you find the relevant URL, copy it and use it in your Puppeteer script to track and capture those responses directly.

Go to DevTools → Network tab → Filter by fetch → Copy relevant URLs → Use above pattern to track responses.

Here’s how you can intercept and analyze network requests using Puppeteer:

await page.setRequestInterception(true);

page.on("request", (req) => {
  if (req.resourceType() === "fetch") {
    console.log("Fetching:", req.url());
  }
  req.continue();
});

page.on("response", async (response) => {
  const req = response.request();
  if (req.url().includes("/api/target-data")) {
    const json = await response.json();
    console.log("Captured API response:", json);
  }
});

4. Filtering the Scraped Data Using AI

Once you have the raw data, clean and filter it using a prompt to find relevant targets.

Relevancy Scoring (Prompt-based AI)

const { OpenAI } = require("openai");
const openai = new OpenAI({ apiKey: "YOUR_API_KEY" });

async function getRelevancyScore(profile) {
  const prompt = `
  Analyze this profile: ${JSON.stringify(profile)}
  Give a score between 0 to 10 based on how well they match someone looking for web development services.
  `;

  const res = await openai.chat.completions.create({
    model: "gpt-4",
    messages: [{ role: "user", content: prompt }],
  });

  return res.choices[0].message.content.trim();
}

Craft a custom message that's uniquely tailored to each client.

async function generateMessage(profile) {
  const prompt = `
  Write a personalized outreach message for this person: ${JSON.stringify(profile)}
  They are a great fit for offering a web development service. Keep the message short and friendly.
  `;

  const res = await openai.chat.completions.create({
    model: "gpt-4",
    messages: [{ role: "user", content: prompt }],
  });

  return res.choices[0].message.content.trim();
}

5. Outreach: Human-like Behavior

Many platforms now track your typing speed, mouse movements, and click patterns to detect whether actions are performed by a real human or a bot. To avoid getting flagged, it's important to automate outreach in a way that mimics natural human behavior—this includes randomizing delays, varying message formats, and using typing patterns that look real. This technique is called humanization, and it's key to making your automation appear genuine

Typing Simulation

await page.type("textarea.message", message, { delay: 50 });

Mouse Click Simulation

const button = await page.$("button.send");
const boundingBox = await button.boundingBox();
await page.mouse.click(boundingBox.x + 5, boundingBox.y + 5, { delay: 100 });

Adding random waits between actions also helps:

await page.waitForTimeout(Math.floor(Math.random() * 2000) + 1000);

6. Track and Analyze Responses

After outreach, monitor incoming messages and use AI to classify the response:

async function analyzeResponse(text) {
  const prompt = `
  Is the following message a positive response to a cold outreach? 
  Message: "${text}"
  Answer with YES or NO.
  `;

  const res = await openai.chat.completions.create({
    model: "gpt-4",
    messages: [{ role: "user", content: prompt }],
  });

  return res.choices[0].message.content.trim();
}

You can poll the inbox or listen to incoming messages via selectors and analyze their content using the above function.


Final Words

With this system in place, you’ve built:

✅ A fully automated browser agent using Puppeteer
✅ A login system with persistent session storage
✅ Smart scraping via network/API interception
✅ AI-powered filtering and personalized targeting
✅ Human-like interaction patterns to bypass detection
✅ Lead response tracking to focus on hot prospects

Now, scale it, fine-tune your prompts, analyze what works—and you’ll be able to turn hundreds (even thousands) of cold leads into real, engaged conversations.


If you found this guide helpful, give it a like and feel free to reach out with questions, collaborations, or feedback at shivangsingh2240@gmail.com — I’d love to hear from you! 🙌

Happy Automating!

0
Subscribe to my newsletter

Read articles from Shivang Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Shivang Singh
Shivang Singh