Ai Email Writer
Ai Email Writer on ApifyForge — AI cold email personalization at $0.01 per email — with zero markup on LLM costs. This actor takes your enriched lead data, connects to your own OpenAI or Anthropic API key, and generates fully personalized cold emails for each prospect: subject line, opening line, body, CTA, and an optional follow-up sequence.
Maintenance Pulse
90/100Documentation
AI cold email personalization at $0.01 per email — with zero markup on LLM costs. This actor takes your enriched lead data, connects to your own OpenAI or Anthropic API key, and generates fully personalized cold emails for each prospect: subject line, opening line, body, CTA, and an optional follow-up sequence.
Built for sales teams, SDRs, and growth agencies that want AI-written outreach at scale without paying Clay's Actions credit tax. Your LLM API key goes straight to OpenAI or Anthropic — no middleman margin. You only pay $0.01 per email to cover Apify compute.
What does AI Cold Email Writer generate?
| Data Point | Source | Example |
|---|---|---|
| 📧 Subject line | AI-generated | Scaling your eng team post-Series B |
| ✉️ Email body | AI-generated | Full 50-180 word email with personalized opening |
| 🎯 Opening line | AI-generated | Congrats on the $20M round — that kind of growth always surfaces deployment bottlenecks. |
| 📣 Call to action | AI-generated | Are you open to a 15-minute call this week? |
| 📋 Full email | Assembled output | Subject + body + signature, ready to copy-paste |
| 🔁 Follow-up email | AI-generated (optional) | 30-60 word follow-up with new angle |
| 🏷️ Personalization points | AI self-reported | ["Series B funding", "VP Engineering title", "deployment friction pain point"] |
| 📊 Word count | Calculated | 67 |
| 🔢 Tokens used | LLM metadata | 312 |
| 👤 Lead echo fields | Pass-through | Name, email, company, title |
| 🤖 Model used | Metadata | gpt-4o-mini |
| 🕒 Generated at | Timestamp | 2026-03-23T14:32:00.000Z |
Why use AI Cold Email Writer?
Manual personalization is the bottleneck of every outbound sequence. A skilled SDR can write 20-30 genuinely personalized emails per day. With enriched lead data sitting in a spreadsheet, most teams either send generic blasts (low response rates) or pay copywriters and expensive SaaS tools (high cost).
Clay is the category leader for AI email personalization — but it charges Actions credits even when you supply your own API key. At $149/month for 35,000 Actions, that is $0.0043 per action before you even factor in API costs. This actor charges $0.01 per email for compute only, and your API key calls OpenAI or Anthropic directly with zero markup.
- Scheduling — run daily to generate emails as new leads are enriched, or batch once a week for your outreach sequence
- API access — trigger from Python, JavaScript, n8n, or any HTTP client to integrate into your existing sales stack
- Spending limits — set a maximum spend per run so a large lead list never surprises your Apify budget
- Monitoring — get Slack or email alerts when runs fail or produce unexpected results
- Integrations — push output directly to HubSpot, Google Sheets, Zapier, or any webhook endpoint
Features
- Dual LLM provider support — choose OpenAI (GPT-4o, GPT-4o-mini) or Anthropic (Claude 3.5 Haiku, Claude Sonnet 4) per run; switch models without touching any code
- Bring your own API key, zero LLM markup — your key authenticates directly to
api.openai.comorapi.anthropic.com; no proxying, no token surcharge - Pay-per-event pricing — charged at $0.01 per successfully generated email; failed leads are never charged
- 15+ lead fields supported — name, title, company, industry, services, revenue, company size, location, recent news, pain points, technologies, LinkedIn headline, bio, mutual connections, plus any custom fields in your data
- Custom field pass-through — unknown keys in your lead JSON are automatically appended to the LLM context, so enriched data from any source works without field mapping
- 4 email tones — professional, casual, friendly, or direct; each maps to a specific writing instruction injected into the system prompt
- 3 length targets — short (50-80 words, recommended for cold email), medium (80-120 words), long (120-180 words); the LLM is instructed to stay within the range
- Follow-up sequence generation — optionally generate a 30-60 word follow-up email for each lead with a fresh angle and consistent personalization
- Custom instructions field — append additional directives to the system prompt: reference a specific case study, use the prospect's company name in the subject, avoid a competitor name, or enforce any brand voice rule
- No-filler writing rules — the system prompt explicitly bans "I hope this email finds you well", "I wanted to reach out", "touching base", "circling back", and 5 other spam-trigger phrases
- Structured JSON output — subject line, opening line, body, CTA, and personalization points are output as separate fields, not one undifferentiated blob
- Rate limit retry logic — on HTTP 429 from either provider, the actor waits 5 seconds and retries once before recording a failure
- Hard auth error detection — invalid API keys are detected immediately and halt the run with a clear error message before wasting time on subsequent leads
- Batch dataset flushing — results are pushed to the dataset in batches of 50 to avoid memory pressure on large runs
- Hard cap at 500 leads per run — prevents runaway API costs; run multiple batches for larger lists
Use cases for AI cold email personalization
Sales prospecting and SDR outreach
SDRs building targeted outreach sequences spend 40-60% of their day on manual research and personalization. Feed enriched lead data from Website Contact Scraper or Google Maps Email Extractor into this actor and generate personalized first-touch emails in minutes. Export to CSV and paste directly into your email sequencer.
Marketing agency lead generation
Agencies running outbound campaigns for clients process hundreds of leads per week across multiple verticals. This actor lets you configure different sender contexts, value propositions, and tones per client run — no shared tooling costs, no per-seat SaaS fees. Process a 200-lead list for a client campaign in under 10 minutes.
Recruiting and talent sourcing
Recruiters reaching out to passive candidates need emails that reference specific career signals — current title, company stage, tech stack, LinkedIn headline. Map candidate enrichment data to the lead fields and generate outreach that references their specific context rather than a generic "exciting opportunity" template.
Account-based marketing (ABM)
ABM teams running 1:1 personalized campaigns at named accounts need high-quality, research-backed copy at every touchpoint. Pipe your account research data (funding news, tech stack, pain points, recent hires) into the lead fields to generate emails that read like they were written by someone who spent an hour on the account.
CRM data enrichment and re-engagement
Re-engagement campaigns targeting dormant contacts in your CRM benefit from fresh personalization angles. Feed current company data — recent news, leadership changes, new product launches — alongside the original contact data to generate re-engagement copy that references what has changed since the last touch.
Founder-led outreach
Early-stage founders doing their own outbound can generate a week of personalized emails in one run. Set the senderRole to your title, write a tight value proposition, and let the actor handle the personalization heavy lifting across your prospect list.
How to generate personalized cold emails
-
Prepare your lead data — Create a JSON array where each object represents one prospect. At minimum include
nameandcompanyName. The more fields you add (industry, recentNews, painPoints, linkedinHeadline), the more personalized the output. Paste the array into the "Leads" field in the actor input. -
Add your sender context — Fill in
senderName,senderCompany, andvalueProposition. The value proposition is the most important field — be specific: "We build custom data pipelines that reduce manual reporting time by 80% for Series A-C SaaS companies" performs far better than "We help companies save time." -
Configure your LLM — Select OpenAI or Anthropic, paste your API key into the corresponding field (stored securely, never logged), and choose a model.
gpt-4o-miniis the best cost-quality starting point for most cold email use cases. -
Run the actor and download results — Click "Start" and wait roughly 1-2 seconds per lead. Download output from the Dataset tab as JSON, CSV, or Excel. Each row contains the subject line, full email, and follow-up (if enabled) ready for your sequencer.
Input parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
leads | array | Yes | — | Array of lead objects. Any field is valid; standard fields get special handling. |
senderName | string | Yes | — | Your full name, used in the email signature. |
senderCompany | string | Yes | — | Your company name, used in the system prompt and signature. |
valueProposition | string | Yes | — | What you are offering. The more specific, the better the output. |
llmProvider | string | No | openai | Which AI provider to use: openai or anthropic. |
openaiApiKey | string | Conditional | — | Your OpenAI API key (sk-...). Required when llmProvider is openai. Stored as a secret. |
anthropicApiKey | string | Conditional | — | Your Anthropic API key (sk-ant-...). Required when llmProvider is anthropic. Stored as a secret. |
llmModel | string | No | gpt-4o-mini | Model name. OpenAI: gpt-4o-mini, gpt-4o. Anthropic: claude-haiku-3-5-20241022, claude-sonnet-4-20250514. |
senderRole | string | No | "" | Your job title. Appears in the email signature if provided. |
emailTone | string | No | professional | Tone: professional, casual, friendly, or direct. |
emailLength | string | No | short | Body length: short (50-80 words), medium (80-120), or long (120-180). |
includeFollowUp | boolean | No | false | Generate a 30-60 word follow-up email for each lead. Doubles LLM calls. |
customInstructions | string | No | "" | Extra directives appended to the system prompt for every email in this run. |
maxLeads | integer | No | 100 | Maximum leads to process in this run. Hard cap at 500. |
Input examples
Single lead, minimal fields:
{
"leads": [
{
"name": "Sarah Chen",
"email": "[email protected]",
"jobTitle": "VP of Engineering",
"companyName": "Acme Corp",
"industry": "SaaS",
"recentNews": "Recently raised $20M Series B"
}
],
"llmProvider": "openai",
"openaiApiKey": "sk-...",
"llmModel": "gpt-4o-mini",
"senderName": "Jordan Rivera",
"senderCompany": "DataPipe Labs",
"senderRole": "Head of Partnerships",
"valueProposition": "We build automated data pipelines that cut manual reporting time by 80% for SaaS companies scaling past Series B.",
"emailTone": "professional",
"emailLength": "short"
}
Batch run with follow-up sequence and custom instructions:
{
"leads": [
{
"name": "James Miller",
"email": "[email protected]",
"jobTitle": "Head of Growth",
"companyName": "BuildCo",
"industry": "Construction Technology",
"services": "Project management software for contractors",
"painPoints": "Low trial-to-paid conversion, high CAC",
"technologies": "HubSpot, Segment, Mixpanel"
},
{
"name": "Priya Nair",
"email": "[email protected]",
"jobTitle": "Director of Marketing",
"companyName": "Meridian Health",
"industry": "Healthcare SaaS",
"companySize": "200-500",
"recentNews": "Launched new patient engagement platform Q1 2026"
}
],
"llmProvider": "anthropic",
"anthropicApiKey": "sk-ant-...",
"llmModel": "claude-haiku-3-5-20241022",
"senderName": "Marcus Webb",
"senderCompany": "Clarity Analytics",
"senderRole": "Founder",
"valueProposition": "We turn scattered product analytics into a single revenue dashboard that shows exactly where trials drop off — in 48 hours, no engineering work required.",
"emailTone": "direct",
"emailLength": "short",
"includeFollowUp": true,
"customInstructions": "Always reference the prospect's tech stack in the opening if available. Never mention Amplitude or Mixpanel by name.",
"maxLeads": 50
}
Anthropic Claude with rich lead fields:
{
"leads": [
{
"firstName": "Elena",
"lastName": "Vasquez",
"email": "[email protected]",
"title": "COO",
"company": "Pinnacle Logistics",
"industry": "Supply Chain",
"revenue": "$50M-$100M",
"location": "Chicago, IL",
"linkedinHeadline": "COO @ Pinnacle | Building resilient supply chains for mid-market retail",
"recentNews": "Expanded into Southeast Asian markets in Jan 2026",
"painPoints": "Cross-border customs delays, real-time shipment visibility"
}
],
"llmProvider": "anthropic",
"anthropicApiKey": "sk-ant-...",
"llmModel": "claude-sonnet-4-20250514",
"senderName": "Tom Bradley",
"senderCompany": "FreightSight",
"valueProposition": "We provide real-time customs pre-clearance intelligence that reduces cross-border delays by 60% for mid-market logistics companies.",
"emailTone": "friendly",
"emailLength": "medium"
}
Input tips
- Write a tight value proposition — the actor's system prompt feeds your
valuePropositiondirectly to the LLM as the core brief. One specific, quantified sentence outperforms three vague ones. - Include recent news and pain points — these two fields produce the most distinctive opening lines. Even one sentence of context ("just raised Series B", "launching in APAC") transforms generic copy into something that reads as researched.
- Use
gpt-4o-minifor most runs — quality is indistinguishable from GPT-4o for cold email at roughly 5x lower cost. Switch togpt-4oorclaude-sonnet-4-20250514only for high-value enterprise targets. - Keep
emailLengthonshort— response rates for cold email consistently favor 50-80 word bodies. Reservemediumandlongfor warm introductions or ABM accounts. - Set
maxLeadsto your batch size — if you are processing 500 leads, setmaxLeadsto 500 and set a spending limit in Apify to cap the run at your budget ceiling.
Output example
{
"leadName": "Sarah Chen",
"leadEmail": "[email protected]",
"leadCompany": "Acme Corp",
"leadTitle": "VP of Engineering",
"subjectLine": "Acme's Series B and deployment bottlenecks",
"openingLine": "Congrats on the $20M round — that kind of velocity usually surfaces deployment pipeline friction before the next headcount wave arrives.",
"emailBody": "Congrats on the $20M round — that kind of velocity usually surfaces deployment pipeline friction before the next headcount wave arrives.\n\nWe work with engineering leaders at Series B SaaS companies to build automated data pipelines that cut the manual reporting overhead so your team ships instead of compiling dashboards.\n\nAre you open to a 15-minute call this week to see if it's relevant?",
"callToAction": "Are you open to a 15-minute call this week to see if it's relevant?",
"fullEmail": "Subject: Acme's Series B and deployment bottlenecks\n\nCongrats on the $20M round — that kind of velocity usually surfaces deployment pipeline friction before the next headcount wave arrives.\n\nWe work with engineering leaders at Series B SaaS companies to build automated data pipelines that cut the manual reporting overhead so your team ships instead of compiling dashboards.\n\nAre you open to a 15-minute call this week to see if it's relevant?\n\nBest,\nJordan Rivera\nHead of Partnerships\nDataPipe Labs",
"followUpSubject": "Re: Acme's Series B and deployment bottlenecks",
"followUpBody": "Wanted to add one thing — we recently helped a SaaS company at your stage cut their sprint reporting time from 6 hours to 20 minutes. Happy to share the details if it's useful. Still open to that quick call?",
"personalizationPoints": [
"Series B funding round ($20M)",
"VP of Engineering title",
"SaaS industry context",
"Scaling engineering team pain point"
],
"wordCount": 67,
"llmModel": "gpt-4o-mini",
"generatedAt": "2026-03-23T14:32:11.442Z",
"tokensUsed": 341
}
Output fields
| Field | Type | Description |
|---|---|---|
leadName | string | null | Prospect name, echoed from input. |
leadEmail | string | null | Prospect email address, echoed from input. |
leadCompany | string | null | Company name, echoed from input. |
leadTitle | string | null | Job title, echoed from input. |
subjectLine | string | AI-generated subject line (under 50 characters). |
openingLine | string | First sentence of the email body. Personalized and hook-focused. |
emailBody | string | Full email body including opening line and CTA. No signature. |
callToAction | string | The CTA sentence extracted from the body. |
fullEmail | string | Complete email: subject line header, body, and signature. Copy-paste ready. |
followUpSubject | string | null | Follow-up subject line. Null if includeFollowUp is false or generation failed. |
followUpBody | string | null | Follow-up email body (30-60 words). Null if includeFollowUp is false. |
personalizationPoints | string[] | List of specific data points the LLM used to personalize the email. |
wordCount | integer | Word count of emailBody. |
llmModel | string | The model that generated this email. |
generatedAt | string | ISO 8601 timestamp of generation. |
tokensUsed | integer | null | Total tokens consumed for this email (input + output). Null if not reported by the provider. |
The dataset also includes a summary record as the final row with fields: type, totalProcessed, succeeded, failed, spendingLimitReached, provider, llmModel, includeFollowUp, completedAt.
How much does it cost to generate AI cold emails?
AI Cold Email Writer uses pay-per-event pricing — you pay $0.01 per email successfully generated. Compute costs are included. Failed leads are not charged. Your LLM API costs are separate and paid directly to OpenAI or Anthropic — there is no markup here.
| Scenario | Emails | Apify cost | LLM cost (gpt-4o-mini est.) | Total |
|---|---|---|---|---|
| Quick test | 5 | $0.05 | ~$0.01 | ~$0.06 |
| Small campaign | 50 | $0.50 | ~$0.10 | ~$0.60 |
| Weekly batch | 200 | $2.00 | ~$0.40 | ~$2.40 |
| Monthly campaign | 500 | $5.00 | ~$1.00 | ~$6.00 |
| With follow-ups (2x LLM calls) | 200 | $2.00 | ~$0.80 | ~$2.80 |
You can set a maximum spending limit per run to control costs. The actor stops when your budget is reached and saves all emails generated so far.
Compare this to Clay at $149/month for their Starter plan — a typical 200-lead enrichment and personalization workflow burns through their Actions credits quickly, and you still pay the markup on top of your API key. With this actor, 200 emails costs roughly $2.40 total with no subscription.
Generate AI cold emails using the API
Python
from apify_client import ApifyClient
client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("ryanclinton/ai-email-writer").call(run_input={
"leads": [
{
"name": "Sarah Chen",
"email": "[email protected]",
"jobTitle": "VP of Engineering",
"companyName": "Acme Corp",
"industry": "SaaS",
"recentNews": "Recently raised $20M Series B",
"painPoints": "Scaling engineering team, reducing deployment friction"
}
],
"llmProvider": "openai",
"openaiApiKey": "sk-...",
"llmModel": "gpt-4o-mini",
"senderName": "Jordan Rivera",
"senderCompany": "DataPipe Labs",
"senderRole": "Head of Partnerships",
"valueProposition": "We build automated data pipelines that cut manual reporting time by 80% for SaaS companies scaling past Series B.",
"emailTone": "professional",
"emailLength": "short",
"includeFollowUp": False
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item.get("type") == "summary":
print(f"Done: {item['succeeded']} emails generated")
elif item.get("subjectLine"):
print(f"To: {item['leadName']} ({item['leadEmail']})")
print(f"Subject: {item['subjectLine']}")
print(f"---\n{item['emailBody']}\n")
JavaScript
import { ApifyClient } from "apify-client";
const client = new ApifyClient({ token: "YOUR_API_TOKEN" });
const run = await client.actor("ryanclinton/ai-email-writer").call({
leads: [
{
name: "Sarah Chen",
email: "[email protected]",
jobTitle: "VP of Engineering",
companyName: "Acme Corp",
industry: "SaaS",
recentNews: "Recently raised $20M Series B",
painPoints: "Scaling engineering team, reducing deployment friction"
}
],
llmProvider: "openai",
openaiApiKey: "sk-...",
llmModel: "gpt-4o-mini",
senderName: "Jordan Rivera",
senderCompany: "DataPipe Labs",
senderRole: "Head of Partnerships",
valueProposition: "We build automated data pipelines that cut manual reporting time by 80% for SaaS companies scaling past Series B.",
emailTone: "professional",
emailLength: "short",
includeFollowUp: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) {
if (item.subjectLine) {
console.log(`To: ${item.leadName} <${item.leadEmail}>`);
console.log(`Subject: ${item.subjectLine}`);
console.log(item.emailBody);
console.log("---");
}
}
cURL
# Start the actor run
curl -X POST "https://api.apify.com/v2/acts/ryanclinton~ai-email-writer/runs?token=YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"leads": [
{
"name": "Sarah Chen",
"email": "[email protected]",
"jobTitle": "VP of Engineering",
"companyName": "Acme Corp",
"industry": "SaaS",
"recentNews": "Recently raised $20M Series B"
}
],
"llmProvider": "openai",
"openaiApiKey": "sk-...",
"llmModel": "gpt-4o-mini",
"senderName": "Jordan Rivera",
"senderCompany": "DataPipe Labs",
"valueProposition": "We build automated data pipelines that cut manual reporting time by 80% for Series B SaaS companies.",
"emailTone": "professional",
"emailLength": "short"
}'
# Fetch results (replace DATASET_ID from the run response above)
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_API_TOKEN&format=json"
How AI Cold Email Writer works
Lead data ingestion and field normalization
The actor accepts any JSON object as a lead record. Standard fields (name/firstName/lastName, jobTitle/title, companyName/company) are normalized so output from different enrichment tools works without field remapping. Any key not in the known set is automatically appended to the LLM context string as key: value. This means enrichment output from Waterfall Contact Enrichment, Apollo, Clay, or your own scrapers can be passed directly.
System prompt construction
A system prompt is built once per run (not per lead) from your sender context, value proposition, tone setting, length target, and custom instructions. The tone maps to one of four specific writing directives — for example, direct maps to "Write in a direct, punchy tone. No fluff. Get to the point immediately." The length target maps to word count ranges (short = 50-80 words). Nine explicit anti-spam rules are injected: the LLM is instructed to avoid "I hope this email finds you well", "I wanted to reach out", "touching base", "circling back", and similar phrases. The subject line is constrained to under 50 characters, no exclamation marks. The output format is specified as strict JSON with five named keys.
LLM API call and JSON parsing
For each lead, the actor builds a user message containing the formatted lead data summary and calls either api.openai.com/v1/chat/completions (with response_format: {type: "json_object"} enforced) or api.anthropic.com/v1/messages using anthropic-version: 2023-06-01. Both calls use temperature: 0.7 and max_tokens: 1024. A 30-second fetch timeout is applied with AbortController. If the primary parse fails, a regex fallback attempts to extract JSON from markdown code fences or raw prose before treating the response as plain text. Rate limit errors (HTTP 429) trigger a 5-second wait and a single retry. Invalid API key errors (HTTP 401) and model-not-found errors (HTTP 404) are treated as fatal and halt the run immediately.
Follow-up sequence generation
When includeFollowUp is true, a second LLM call is made per lead using a separate follow-up system prompt. The follow-up prompt references the original subject line, constrains the output to 30-60 words, and instructs the model to add a new angle rather than repeat the first email. A 500ms delay is applied between the primary email call and the follow-up call to reduce rate limit pressure. The follow-up is charged as part of the same PPE event as the primary email — one charge per lead regardless of whether follow-up is enabled.
Tips for best results
-
Include
recentNewsandpainPointswhenever possible. These two fields produce the most distinctive, non-generic opening lines. Even a single sentence — "just expanded to APAC" or "recently hired a new CFO" — gives the model something concrete to anchor the opening. -
Test your value proposition on 3-5 leads before a large batch. The value proposition is injected into every email. If it is vague, every email will be vague. Run a test batch, read the output, and refine before scaling to hundreds.
-
Use
gpt-4o-minifor prospecting,gpt-4oorclaude-sonnet-4-20250514for high-value accounts. The quality difference is real but small for cold email. Save the expensive models for enterprise deals where a bespoke feel matters. -
Set a spending limit in Apify for large batches. Go to Actor Settings and set a maximum run cost. The actor checks
eventChargeLimitReachedafter each email and stops cleanly if the limit is hit, preserving all emails generated so far. -
Combine with Waterfall Contact Enrichment for a complete pipeline. Enrich your leads first to populate recentNews, technologies, LinkedIn headline, and painPoints fields. Richer input data consistently produces more personalized output.
-
Use
customInstructionsfor brand voice rules. If your sales team has guardrails — always mention a specific case study, never use certain words, always include a specific statistic — inject them here rather than post-editing each email manually. -
Download output as CSV for direct import into your sequencer. The
subjectLine,emailBody,followUpSubject, andfollowUpBodycolumns map directly to the fields most sequencers (Outreach, Salesloft, Smartlead, Instantly) expect for personalization variables.
Combine with other Apify actors
| Actor | How to combine |
|---|---|
| Waterfall Contact Enrichment | Run enrichment first to populate pain points, technologies, LinkedIn headline, and recent news fields, then feed the enriched output directly into this actor as the leads array. |
| Website Contact Scraper | Scrape contact emails and job titles from a list of company websites, then pass the structured output to this actor for personalized outreach. |
| Google Maps Email Extractor | Extract local business leads with contact details from Google Maps, then use this actor to generate personalized cold emails for each business owner or manager. |
| B2B Lead Gen Suite | Use the full lead pipeline (website scraping → enrichment → scoring) and pass scored, enriched leads into this actor to generate copy only for leads above a quality threshold. |
| HubSpot Lead Pusher | After generating emails, push the output (lead fields + generated copy) into HubSpot as contact notes or custom properties for use in sequences. |
| Email Pattern Finder | Verify the email naming convention for a target domain before sending, ensuring your emails reach the right address. |
| Bulk Email Verifier | Verify the deliverability of each email address in your list before running this actor to avoid wasting generation credits on invalid addresses. |
Limitations
- Maximum 500 leads per run. For larger lists, run multiple batches. The
maxLeadscap prevents runaway LLM costs on accidentally large inputs. - LLM output quality depends on input data quality. Leads with only a name and company name will produce less personalized output than leads with recent news, pain points, and LinkedIn context. The model cannot invent context it was not given.
- No built-in email address discovery. This actor generates email copy; it does not find email addresses. Use Website Contact Scraper or Google Maps Email Extractor to find addresses first.
- LLM API costs are separate and billed to your account by OpenAI or Anthropic. For 200 emails with
gpt-4o-mini, expect approximately $0.40-$0.60 in LLM costs on top of the $2.00 Apify compute fee. - Rate limits on your LLM API key may slow down large batches. New API keys from OpenAI have low rate limits by default. If you see frequent rate limit warnings, upgrade your OpenAI usage tier or use Anthropic as a fallback.
- The actor does not validate email content against CAN-SPAM or GDPR requirements. The generated copy is a starting point. Review all emails before sending to ensure compliance with applicable law.
- Model names must match the provider's current model IDs exactly. Using a deprecated or misspelled model name causes the run to fail with a clear error on the first lead. Use
gpt-4o-mininotgpt4o-mini. - Custom instructions cannot override core writing rules. The no-filler-phrase rules and JSON output format are hardcoded in the system prompt and cannot be disabled via
customInstructions.
Integrations
- Zapier — trigger this actor when a new row is added to a Google Sheet of leads, then push the generated email directly to Gmail Drafts or a Slack channel for review
- Make — build a full outbound automation: Google Maps search → contact scraping → email generation → CRM record creation
- Google Sheets — export the dataset directly to a Sheet; use the
subjectLineandemailBodycolumns as mail-merge variables in Gmail or Sheets-connected sequencers - Apify API — call the actor programmatically from your sales ops scripts to generate emails on demand as new leads enter your pipeline
- Webhooks — trigger a webhook on run completion to notify your team in Slack or post results to an internal dashboard
- LangChain / LlamaIndex — use the Apify dataset loader to pull generated emails into an AI agent that further classifies or routes them based on lead score or industry
Troubleshooting
-
"Invalid OpenAI API key" error on the first lead — The run halts immediately on auth errors to prevent wasting credits. Check that you pasted the full key including the
sk-prefix and that the key is active in your OpenAI account at platform.openai.com. -
Emails are too generic despite rich lead data — This is almost always caused by a vague
valueProposition. Rewrite it to be specific and quantified: include the type of company you serve, the problem you solve, and the result you deliver. Then re-run a test batch. -
Run produces some empty
emailBodyfields — Individual leads fail when the LLM returns an unparseable response. The actor records the failure and continues to the next lead. Check thewordCount: 0rows in your dataset; these are the failed leads. Re-running with the same input for just those leads will usually succeed. -
Rate limit warnings slowing down the run — You will see "Rate limited by LLM API. Waiting 5 seconds before retry..." in the logs. This is handled automatically with one retry. For large batches, upgrade your OpenAI tier or switch to Anthropic which has higher default rate limits for new keys.
-
Follow-up emails are too similar to the primary email — Add a
customInstructionsdirective such as "For the follow-up, focus on a specific customer result or ROI number, not the product description." The follow-up system prompt instructs the model to add a new angle but a specific instruction produces more differentiated copy.
Responsible use
- This actor generates email copy from lead data you supply. You are responsible for how that data was obtained.
- Comply with CAN-SPAM, CASL, GDPR, and other applicable laws before sending any generated emails.
- Do not use generated emails for spam, phishing, impersonation, or any form of deceptive outreach.
- Your API key is transmitted securely to OpenAI or Anthropic and is never logged or stored by this actor.
- For guidance on email outreach compliance, review the requirements of your jurisdiction and your email service provider's terms.
FAQ
How much does AI cold email personalization cost with this actor?
You pay $0.01 per email to Apify for compute. LLM costs are separate and go directly to OpenAI or Anthropic from your API key. With gpt-4o-mini, expect roughly $0.002 per email in LLM costs, bringing the total to around $0.012 per email — or about $1.20 per 100 emails.
How is this different from Clay for AI email personalization? Clay charges Actions credits even when you bring your own OpenAI API key. Their Starter plan at $149/month includes a limited number of Actions, and enrichment plus AI personalization consume credits fast. This actor charges only $0.01/email compute with zero markup on your API costs. For a 200-lead campaign, Clay's Actions cost is bundled into a subscription; here the total cost is roughly $2.40, no subscription.
Can I use Claude (Anthropic) instead of OpenAI?
Yes. Set llmProvider to anthropic, add your anthropicApiKey, and set llmModel to claude-haiku-3-5-20241022 (fast) or claude-sonnet-4-20250514 (highest quality). The same prompts and output format are used for both providers.
How many leads can I process in one run?
Up to 500 leads per run. For larger lists, split into batches of 500 and run them sequentially. The maxLeads parameter defaults to 100 — set it to 500 to process the maximum in one run.
What lead fields produce the best personalization?
recentNews and painPoints produce the most distinctive opening lines. linkedinHeadline and bio help the model write to the person, not just the company. technologies is valuable for technical products. At minimum, provide name, jobTitle, companyName, and industry.
Is it legal to use AI to write cold emails? Writing cold emails with AI assistance is legal. The legal requirements relate to how you send them, not how you write them. You must comply with CAN-SPAM (US), CASL (Canada), GDPR (EU), and similar regulations: include a physical address, provide an unsubscribe mechanism, and only contact people who have a legitimate business relationship or a lawful basis for contact. See Apify's guide on web scraping legality for context on data sourcing.
Can I generate follow-up emails in the same run?
Yes. Set includeFollowUp to true. The actor makes a second LLM call per lead to generate a 30-60 word follow-up with a fresh angle. Follow-ups are stored in followUpSubject and followUpBody on the same output row as the primary email. A 500ms delay is applied between the primary and follow-up calls to reduce rate limiting.
How accurate is the personalization — does the AI invent details? The actor instructs the model to use only the data provided and not to invent facts. However, LLMs can occasionally hallucinate. Review generated emails before sending, particularly for specific claims like metrics or product details not present in your lead data.
Can I schedule this actor to run on a recurring basis? Yes. Use Apify's built-in scheduling to run the actor daily, weekly, or on any cron schedule. Feed it a fresh lead list each run by connecting the input to a Google Sheet or dataset via the Apify API.
What happens if my OpenAI API key hits its rate limit mid-run? The actor detects HTTP 429 responses, waits 5 seconds, and retries once. If the retry also fails, the lead is recorded as failed and the actor continues to the next lead. No charge is applied for failed leads.
Can I use custom OpenAI fine-tuned models?
Yes. The llmModel field accepts any string and passes it directly to the API. If your organization has a fine-tuned model ID, enter it in the llmModel field. The actor will use it as long as the model ID is accessible by your API key.
Does this actor work with enrichment output from other Apify actors?
Yes. The lead ingestion is flexible: it normalizes common field name variants (name/firstName+lastName, jobTitle/title, companyName/company) and passes unknown fields through automatically. Output from Waterfall Contact Enrichment or B2B Lead Gen Suite can be passed directly.
Help us improve
If you encounter issues, you can help us debug faster by enabling run sharing in your Apify account:
- Go to Account Settings > Privacy
- Enable Share runs with public Actor creators
This lets us see your run details when something goes wrong so we can fix issues faster. Your data is only visible to the actor developer, not publicly.
Support
Found a bug or have a feature request? Open an issue in the Issues tab on this actor's page. For custom solutions or enterprise integrations — bulk email generation pipelines, CRM integrations, custom model configurations — reach out through the Apify platform.
How it works
Configure
Set your parameters in the Apify Console or pass them via API.
Run
Click Start, trigger via API, webhook, or set up a schedule.
Get results
Download as JSON, CSV, or Excel. Integrate with 1,000+ apps.
Use cases
Sales Teams
Build targeted lead lists with verified contact data.
Marketing
Research competitors and identify outreach opportunities.
Data Teams
Automate data collection pipelines with scheduled runs.
Developers
Integrate via REST API or use as an MCP tool in AI workflows.
Related actors
GitHub Repository Search
Search GitHub repositories by keyword, language, topic, stars, forks. Sort by stars, forks, or recently updated. Returns metadata, topics, license, owner info, URLs. Free API, optional token for higher limits.
Weather Forecast Search
Get weather forecasts for any location worldwide using the free Open-Meteo API. Returns current conditions, daily and hourly forecasts with temperature, precipitation, wind, UV index, and more. No API key needed.
EUIPO EU Trademark Search
Search EU trademarks via official EUIPO database. Find registered and pending trademarks by name, Nice class, applicant, or status. Returns full trademark details and filing history.
Nominatim Address Geocoder
Geocode addresses to GPS coordinates and reverse geocode coordinates to addresses using OpenStreetMap Nominatim. Batch geocoding with rate limiting. Free, no API key needed.