OTHER

Salesforce Lead Pusher

Salesforce Lead Pusher on ApifyForge — Salesforce Lead Pusher takes enriched lead data from any source and pushes it directly into your Salesforce CRM as Leads, Contacts, or Accounts — with automatic deduplication by email, 200-record batch upserts, and a dry-run preview mode that costs nothing. Built for sales teams and RevOps engineers who want a direct pipeline from Apify scrapers into Salesforce without writing Apex code.

0
Users (30d)
0
Runs (30d)
90
Actively maintained
Maintenance Pulse
Free
Per event

Maintenance Pulse

90/100
Last Build
Today
Last Version
1d ago
Builds (30d)
8
Issue Response
N/A

Documentation

Salesforce Lead Pusher takes enriched lead data from any source and pushes it directly into your Salesforce CRM as Leads, Contacts, or Accounts — with automatic deduplication by email, 200-record batch upserts, and a dry-run preview mode that costs nothing. Built for sales teams and RevOps engineers who want a direct pipeline from Apify scrapers into Salesforce without writing Apex code.

Connect it to any Apify actor output — B2B Lead Gen Suite, Google Maps Lead Enricher, Website Contact Scraper, or a plain CSV — and your Salesforce records update automatically. The actor handles OAuth authentication, field normalization, rate-limit retries, and per-record error reporting in a single run.

What data can you push to Salesforce?

Data PointSalesforce FieldExample
📧 EmailEmail[email protected]
👤 Full name (auto-split)FirstName + LastNameSarah / Chen
📞 PhonePhone+1-415-555-0192
📱 MobileMobilePhone+1-415-555-8847
🏢 Company nameCompany (Lead) / Name (Account)Acme Corp
💼 Job titleTitleVP of Engineering
🌐 Website / DomainWebsitehttps://acmecorp.com
🏭 IndustryIndustryTechnology
📍 City, State, CountryCity / State / CountrySan Francisco / CA / US
🏷️ Lead sourceLeadSourceWeb
RatingRatingHot
👥 Employee countNumberOfEmployees250
💰 Annual revenueAnnualRevenue12000000
📝 Description / NotesDescriptionMet at SaaStr 2025
🏷️ Custom fieldsAny Field__cLinkedIn_URL__c

Why use Salesforce Lead Pusher?

Building a manual import workflow for every lead source is the kind of work that never actually gets done. Someone exports a CSV, someone else reformats columns to match Salesforce field names, duplicates slip in, the import fails on bad data, and by the time the leads land in CRM the outreach window has closed. Most teams fall back to copy-pasting or abandon the pipeline entirely.

This actor automates the entire process: authenticate once, point it at a dataset, and every qualifying lead lands in Salesforce as a structured record — deduplicated against what already exists, with all standard fields mapped automatically and custom fields handled via a JSON mapping config.

  • Scheduling — run daily, weekly, or on a trigger to push fresh leads as they arrive from your scraping pipeline
  • API access — call from Python, JavaScript, or any HTTP client to embed this in an existing orchestration layer
  • Proxy rotation — not needed for CRM pushes, but Apify's infrastructure handles reliable outbound connectivity
  • Monitoring — receive Slack or email alerts when a run fails, producing zero records, or hits Salesforce rate limits
  • Integrations — chain via Dataset ID from any other Apify actor, or trigger via Zapier, Make, or webhooks

Features

  • OAuth 2.0 username-password authentication — connects to any Salesforce org using a Connected App Consumer Key + Secret; supports both production (login.salesforce.com) and sandbox (test.salesforce.com) orgs
  • Salesforce Composite Collections API — pushes records 200 at a time using the /composite/sobjects endpoint, the fastest bulk-create path available without governor-limit concerns from Bulk API 2.0 quotas
  • Three object types — push the same lead data as a Lead (unqualified prospect), Contact (person linked to an Account), or Account (company/organisation) depending on where you are in the sales cycle
  • Email-based deduplication — before each batch, runs a SOQL query in chunks of 50 to find existing Leads or Contacts by email; for Accounts, deduplicates by company name. Existing records are skipped and logged
  • Full name splitting"Sarah Chen" becomes FirstName: "Sarah" and LastName: "Chen" automatically; single-word names go to LastName; pre-split firstName/lastName fields pass through unchanged
  • Flexible input normalization — accepts email or emails[], phone or phones[], companyName or company, website or domain, jobTitle or title — compatible with output from any Apify actor without preprocessing
  • Custom field mapping — pass a JSON object to map any input field to any Salesforce API field name, including custom __c fields: {"linkedinUrl": "LinkedIn_URL__c"}
  • Dry-run mode enabled by default — previews every mapped record in the dataset output without creating anything in Salesforce; shows exactly which fields would be set on each record
  • Per-record error reporting — each record in the output carries an action status (created, skipped_duplicate, skipped_dry_run, failed) and an error field with the Salesforce error code and message if the push failed
  • Rate-limit retry — detects REQUEST_LIMIT_EXCEEDED HTTP 403 responses and waits 10 seconds before a single automatic retry; network errors get a 2-second retry
  • Spending limit enforcement — PPE charging fires after data is saved to the dataset; stops cleanly when the run's spending cap is reached rather than crashing mid-batch
  • Summary record — the final dataset item is a type: "summary" record with totals: created, updated, skipped duplicates, skipped dry-run, failed
  • Dataset chaining — provide a datasetId to pull leads directly from another actor's output dataset, up to 5,000 records per run

Use cases for Salesforce lead pushing

Sales prospecting pipeline

SDRs and BDRs using tools like Website Contact Scraper or Google Maps Lead Enricher end up with hundreds of qualified contacts sitting in a spreadsheet. This actor closes the loop: run the scraper, pass its dataset ID to Salesforce Lead Pusher, and every new contact appears in Salesforce within minutes — ready for assignment, sequencing, or automatic lead routing rules.

Marketing agency lead delivery

Agencies running lead gen campaigns for clients need to hand off structured CRM records, not CSV attachments. Point the actor at a completed B2B Lead Gen Suite dataset, set objectType to Lead, and deliver clean Salesforce records directly to the client's org. Duplicates are filtered automatically, so the client never complains about seeing the same contact twice.

RevOps data enrichment

Revenue operations teams enriching existing accounts with fresh firmographic data can push updated fields — employee count, annual revenue, industry — into existing Account records. The fieldMapping config maps any enrichment actor's output field to the correct Salesforce field without touching the existing record structure.

Recruiting and talent sourcing

Recruiters extracting hiring manager contacts from LinkedIn scrapers or conference attendee lists can push directly into Salesforce as Contacts or Leads, with job title, department, and company mapped automatically. The email-based deduplication prevents the same contact from appearing in multiple hiring pipelines.

Automated daily lead imports

Teams running scheduled Apify actors (nightly scrapes, weekly enrichment jobs) can chain Salesforce Lead Pusher at the end of the pipeline via webhooks or the Apify API. New leads from the previous day's run land in Salesforce before the sales team starts work in the morning — no manual import step required.

Conference and event lead capture

After events, lead lists arrive in inconsistent formats. The actor's flexible field normalization handles varying column names (email, emails, Email Address) without preprocessing. Push 500 event leads into Salesforce in one run, with the dry-run preview confirming the mapping looks correct before committing.

How to push leads to Salesforce

  1. Create a Salesforce Connected App — go to Salesforce Setup, search for "App Manager", click "New Connected App". Enable OAuth 2.0, add the api scope, save, and copy your Consumer Key and Consumer Secret. This takes about 5 minutes and only needs to be done once.

  2. Prepare your credentials — your password must be your Salesforce login password concatenated with your security token (no space, no separator). If your password is Summer2025! and your token is abc123XYZ, enter Summer2025!abc123XYZ. Get your security token at Setup > My Personal Information > Reset Security Token.

  3. Configure the actor — paste your Consumer Key, Consumer Secret, username, and combined password into the credential fields. Set objectType to Lead for new prospects. Leave dryRun set to true for the first run. Paste your lead records into the leads array, or enter a datasetId from a previous actor run.

  4. Preview, then push — run with dry-run enabled and check the output dataset. Each record shows which Salesforce fields would be set. When the mapping looks correct, run again with dryRun: false. Results land in Salesforce in under a minute for batches under 1,000 records.

Input parameters

ParameterTypeRequiredDefaultDescription
salesforceUsernamestringYes (live)Salesforce login email, e.g. [email protected]
salesforcePasswordstringYes (live)Password + security token concatenated, no separator
salesforceClientIdstringYes (live)Consumer Key from your Salesforce Connected App
salesforceClientSecretstringYes (live)Consumer Secret from your Salesforce Connected App
salesforceLoginUrlstringNohttps://login.salesforce.comUse https://test.salesforce.com for sandbox orgs
leadsarrayNoInline lead records to push; accepts flexible field names
datasetIdstringNoApify dataset ID to load leads from (up to 5,000 items)
objectTypestringNoLeadSalesforce object: Lead, Contact, or Account
skipDuplicatesbooleanNotrueQuery Salesforce before inserting; skip matching email/name
fieldMappingobjectNo{}Map input fields to Salesforce API field names
dryRunbooleanNotruePreview mapping without writing to Salesforce
maxLeadsintegerNo500Cap records per run (1–5,000)

Input examples

Push a single lead in dry-run mode (recommended first run):

{
  "leads": [
    {
      "name": "Sarah Chen",
      "email": "[email protected]",
      "phone": "+1-415-555-0192",
      "companyName": "Acme Corp",
      "jobTitle": "VP of Engineering",
      "industry": "Technology",
      "website": "https://acmecorp.com",
      "city": "San Francisco",
      "state": "CA",
      "country": "US",
      "description": "Met at SaaStr 2025. Interested in automation tools."
    }
  ],
  "objectType": "Lead",
  "dryRun": true
}

Pull from a dataset and push live to Salesforce with custom field mapping:

{
  "salesforceUsername": "[email protected]",
  "salesforcePassword": "MyPass123TOKEN456abc",
  "salesforceClientId": "3MVG9...",
  "salesforceClientSecret": "1234567890ABCDEF",
  "datasetId": "abc123xyzDatasetId",
  "objectType": "Lead",
  "skipDuplicates": true,
  "fieldMapping": {
    "linkedinUrl": "LinkedIn_URL__c",
    "score": "Lead_Score__c",
    "sourceActor": "Lead_Source_Actor__c"
  },
  "dryRun": false,
  "maxLeads": 500
}

Push to a Salesforce sandbox for testing:

{
  "salesforceUsername": "[email protected]",
  "salesforcePassword": "MyPass123TOKEN456abc",
  "salesforceClientId": "3MVG9...",
  "salesforceClientSecret": "1234567890ABCDEF",
  "salesforceLoginUrl": "https://test.salesforce.com",
  "leads": [
    {
      "name": "Marcus Rivera",
      "email": "[email protected]",
      "companyName": "Beta Industries",
      "jobTitle": "Head of Sales"
    }
  ],
  "objectType": "Lead",
  "dryRun": false
}

Input tips

  • Run dry-run first — always preview with dryRun: true before committing. The output shows every Salesforce field that would be set; check that LastName and Company are populated correctly before going live.
  • Concatenate password + security token — the most common setup error is entering only the password. Salesforce requires the security token appended immediately after the password with no separator.
  • Use sandbox for integration testing — set salesforceLoginUrl to https://test.salesforce.com and append .sandbox to the username (e.g. [email protected]) to push to a sandbox org without touching production data.
  • Chain via datasetId to avoid copy-paste — pass the dataset ID from any other actor's run directly. The actor loads up to 5,000 records automatically, normalizing field name variations across different actor output formats.
  • Use fieldMapping for custom fields — any Salesforce custom field (those ending in __c) must be mapped explicitly. Add {"sourceField": "SalesforceField__c"} to the fieldMapping object for each custom field you want to populate.

Output example

{
  "inputName": "Sarah Chen",
  "inputEmail": "[email protected]",
  "inputCompany": "Acme Corp",
  "salesforceId": "00Q8Z000001GxAbUAK",
  "objectType": "Lead",
  "action": "created",
  "error": null,
  "pushedAt": "2025-09-14T09:22:11.843Z"
}

Summary record (last item in every dataset):

{
  "type": "summary",
  "objectType": "Lead",
  "totalProcessed": 47,
  "created": 39,
  "updated": 0,
  "skippedDuplicates": 7,
  "skippedDryRun": 0,
  "failed": 1,
  "dryRun": false,
  "instanceUrl": "https://mycompany.my.salesforce.com",
  "completedAt": "2025-09-14T09:23:04.217Z"
}

Dry-run record (no Salesforce ID, no charge):

{
  "inputName": "Marcus Rivera",
  "inputEmail": "[email protected]",
  "inputCompany": "Beta Industries",
  "salesforceId": null,
  "objectType": "Lead",
  "action": "skipped_dry_run",
  "error": null,
  "pushedAt": "2025-09-14T09:20:55.012Z"
}

Output fields

FieldTypeDescription
inputNamestring | nullName from the input record as provided
inputEmailstring | nullEmail resolved from email or first item of emails[]
inputCompanystring | nullCompany resolved from companyName or company
salesforceIdstring | nullSalesforce record ID (e.g. 00Q8Z000001GxAb) on success; null otherwise
objectTypestringSalesforce object type: Lead, Contact, or Account
actionstringOne of: created, updated, skipped_duplicate, skipped_dry_run, failed
errorstring | nullSalesforce error code and message if action is failed; null otherwise
pushedAtstringISO 8601 timestamp of when the record was processed
typestring"summary" on the final summary record only
totalProcessedintegerSummary: total records processed in the run
createdintegerSummary: records successfully created in Salesforce
updatedintegerSummary: records updated (reserved; currently always 0)
skippedDuplicatesintegerSummary: records skipped because they already existed
skippedDryRunintegerSummary: records skipped because dry-run was enabled
failedintegerSummary: records that Salesforce rejected with an error
instanceUrlstring | nullSummary: Salesforce instance URL used for this run
completedAtstringSummary: ISO 8601 timestamp when the run finished

How much does it cost to push leads to Salesforce?

Salesforce Lead Pusher uses pay-per-event pricing — you pay $0.05 per lead successfully created in Salesforce. Dry-run runs are completely free. Skipped duplicates are free. Failed records are free. You only pay when a record is actually written to your CRM.

ScenarioLeads pushedCost per leadTotal cost
Quick test (dry-run)Any$0.00$0.00
Small batch10$0.05$0.50
Medium batch100$0.05$5.00
Large batch500$0.05$25.00
Enterprise batch1,000$0.05$50.00

You can set a maximum spending limit per run to control costs. The actor stops cleanly when your budget is reached — no partial batches left in an unknown state.

Compare this to Zapier's Salesforce integration at $49–299/month for automation tasks, or a custom Salesforce integration developer at $150+/hour. Most teams pushing 200–500 leads per week spend under $10/month with no subscription commitment.

Push leads to Salesforce using the API

Python

from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("ryanclinton/salesforce-lead-pusher").call(run_input={
    "salesforceUsername": "[email protected]",
    "salesforcePassword": "MyPass123TOKEN456abc",
    "salesforceClientId": "3MVG9...",
    "salesforceClientSecret": "1234567890ABCDEF",
    "leads": [
        {
            "name": "Sarah Chen",
            "email": "[email protected]",
            "companyName": "Acme Corp",
            "jobTitle": "VP of Engineering",
            "industry": "Technology"
        }
    ],
    "objectType": "Lead",
    "skipDuplicates": True,
    "dryRun": False
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item.get("type") == "summary":
        print(f"Run complete: {item['created']} created, {item['skippedDuplicates']} duplicates skipped")
    elif item.get("action") == "created":
        print(f"Created: {item['inputName']} ({item['inputEmail']}) → SF ID: {item['salesforceId']}")
    elif item.get("action") == "failed":
        print(f"Failed: {item['inputEmail']} — {item['error']}")

JavaScript

import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "YOUR_API_TOKEN" });

const run = await client.actor("ryanclinton/salesforce-lead-pusher").call({
    salesforceUsername: "[email protected]",
    salesforcePassword: "MyPass123TOKEN456abc",
    salesforceClientId: "3MVG9...",
    salesforceClientSecret: "1234567890ABCDEF",
    leads: [
        {
            name: "Marcus Rivera",
            email: "[email protected]",
            companyName: "Beta Industries",
            jobTitle: "Head of Sales",
        }
    ],
    objectType: "Lead",
    skipDuplicates: true,
    dryRun: false,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) {
    if (item.type === "summary") {
        console.log(`Done: ${item.created} created, ${item.skippedDuplicates} skipped, ${item.failed} failed`);
    } else if (item.action === "created") {
        console.log(`Pushed: ${item.inputName} → ${item.salesforceId}`);
    }
}

cURL

# Start the actor run
curl -X POST "https://api.apify.com/v2/acts/ryanclinton~salesforce-lead-pusher/runs?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "salesforceUsername": "[email protected]",
    "salesforcePassword": "MyPass123TOKEN456abc",
    "salesforceClientId": "3MVG9...",
    "salesforceClientSecret": "1234567890ABCDEF",
    "leads": [{"name": "Sarah Chen", "email": "[email protected]", "companyName": "Acme Corp"}],
    "objectType": "Lead",
    "dryRun": false
  }'

# Fetch results (replace DATASET_ID from the run response defaultDatasetId field)
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_API_TOKEN&format=json"

How Salesforce Lead Pusher works

Authentication phase

The actor authenticates using the Salesforce OAuth 2.0 username-password flow, posting credentials to /services/oauth2/token with grant_type=password. This returns an access_token and instance_url specific to your org. The token is reused for all subsequent requests in the run — there is no token refresh logic since runs complete in well under the one-hour token expiry window. In dry-run mode, authentication is skipped entirely.

Deduplication query phase

Before pushing each batch of up to 200 records, the actor runs SOQL queries to find existing records. It queries in chunks of 50 values to stay within URL length limits: SELECT Id, Email FROM Lead WHERE Email IN ('[email protected]', '[email protected]', ...). The result set is loaded into a Set<string> of lowercase lookup keys. For Account objects, the lookup uses Name instead of Email. Records with a matching key are tagged skipped_duplicate without touching Salesforce.

Batch push phase

Active (non-duplicate) records in each batch are mapped to Salesforce field names using mapToSalesforceFields(). This function handles object-type differences — Contact uses MailingCity where Lead uses City, Account uses BillingCity and maps company to Name. Full names are split by whitespace with the last token becoming LastName and everything prior becoming FirstName. The mapped records are submitted to the Salesforce Composite Collections endpoint (/composite/sobjects) in a single POST. The allOrNone: false flag means individual record failures do not roll back the rest of the batch.

Error handling and charging phase

Each item in the Composite API response maps 1-to-1 with the submitted records by position. Records where success: true are logged as created and trigger a PPE charge event (Actor.charge({ eventName: "lead-pushed", count: N })). Records where success: false have their errors[] array serialized into the output error field (statusCode: message format). The actor checks eventChargeLimitReached after each batch charge and stops cleanly if the run's spending cap is hit.

Tips for best results

  1. Always dry-run first. The dry-run output shows exactly which Salesforce fields would be populated for each record. Check that Company is set for Leads (defaults to "Unknown Company" if no company field is found) and that names split correctly before committing a large batch.

  2. Concatenate password and security token correctly. This is the most common configuration error. Your Salesforce security token is a separate alphanumeric string sent to your email when you reset it. It goes immediately after your password with no space or separator. If you change your password, Salesforce resets your token.

  3. Use sandbox for initial integration testing. Set salesforceLoginUrl to https://test.salesforce.com and append .sandbox or the sandbox name to your username (e.g. [email protected]). This lets you verify the full push pipeline against real Salesforce API behavior without risking production data.

  4. Chain with B2B Lead Gen Suite for a full pipeline. Run B2B Lead Gen Suite or Google Maps Lead Enricher to build your lead list, then pass the output datasetId directly to this actor. No CSV export, no reformatting.

  5. Set maxLeads conservatively for testing. When testing with a real production dataset, set maxLeads to 5 or 10 to verify a small sample before processing the full list. This costs $0.25–$0.50 and confirms everything maps correctly.

  6. Map custom fields before you need them. If your Salesforce org has custom fields (Lead_Score__c, Source_Actor__c, LinkedIn_URL__c), configure them in fieldMapping during the dry-run phase. Custom fields must be explicitly mapped — they are not picked up automatically.

  7. Verify the Connected App OAuth scopes. The Connected App must have at minimum the api scope enabled. If you see INSUFFICIENT_ACCESS errors in the output, check Setup > App Manager > your app > OAuth Scopes and add api. The refresh_token scope is not required.

  8. Filter failed records for follow-up. Filter the output dataset by action: "failed" and check the error field. Common failure reasons: REQUIRED_FIELD_MISSING (usually LastName or Company), INVALID_EMAIL_ADDRESS, or FIELD_CUSTOM_VALIDATION_EXCEPTION from org-specific validation rules.

Combine with other Apify actors

ActorHow to combine
B2B Lead Gen SuiteFull pipeline: scrape websites → enrich → push to Salesforce via datasetId
Google Maps Lead EnricherSearch Google Maps for local businesses, enrich with contacts, push as Leads
Website Contact ScraperExtract emails and phones from company websites, push directly as Salesforce Leads
Waterfall Contact EnrichmentEnrich partial records through 10 data sources, then push the enriched output to Salesforce
Email Pattern FinderDiscover email naming patterns for a domain, build full email addresses, push to CRM
Bulk Email VerifierVerify email deliverability before pushing — avoid invalid addresses triggering Salesforce validation errors
HubSpot Lead PusherPush the same lead dataset to HubSpot in parallel for teams using dual CRM setups

Limitations

  • Creates only, no updates. The actor creates new records. It does not update existing Salesforce records — when skipDuplicates is true, existing matches are skipped; when false, Salesforce will return a duplicate error for records that violate your org's duplicate rules. A true upsert (update-on-match) is not currently supported.
  • Up to 5,000 leads per run from a dataset. The listItems call is capped at 5,000 items. For larger datasets, split into multiple runs using maxLeads and offset logic in a parent orchestrator.
  • Password flow requires security token. If your Salesforce org enforces IP restrictions, you must append the security token to the password. Orgs with "trusted IP ranges" covering Apify's IP space may not require it, but this varies by org configuration.
  • No Salesforce Bulk API support. The Composite Collections API is used instead of Bulk API 2.0. This is intentional — Bulk API jobs require polling, add latency, and consume a separate daily job limit quota. The Composite API handles up to 200 records per call with synchronous results.
  • Contact object requires an existing Account. When pushing as Contact, Salesforce requires an AccountId field linking to an existing Account record. The actor does not auto-create Accounts for Contacts. Use the fieldMapping to pass a known AccountId, or push as Lead instead.
  • Custom validation rules may reject records. If your Salesforce org has custom validation rules or required custom fields, records may fail with FIELD_CUSTOM_VALIDATION_EXCEPTION. These are reported in the error field of each failed output record but cannot be handled generically.
  • Sandbox usernames differ from production. Sandbox usernames typically have .sandbox or a sandbox name appended. The actor cannot auto-detect sandbox vs. production from the login URL alone — ensure the username matches the target org.
  • No support for Person Accounts. Salesforce orgs with Person Accounts enabled treat individuals as Accounts rather than Contacts or Leads. The actor does not detect this configuration. Use objectType: "Lead" for person-level records in orgs with Person Accounts.

Integrations

  • Zapier — trigger a Salesforce Lead Pusher run when new leads arrive in a Google Sheet or Airtable base
  • Make — chain actor runs in a Make scenario: scraper → enrichment → Salesforce push in a single automated workflow
  • Google Sheets — export the push results to Google Sheets for stakeholder reporting on leads created vs. duplicates skipped
  • Apify API — trigger runs programmatically from your own CRM middleware or ETL pipeline
  • Webhooks — notify your team via Slack or email when a push run completes, with the summary record included in the payload
  • LangChain / LlamaIndex — use Company Deep Research to generate AI-enriched company summaries, then push the enriched records to Salesforce via this actor

Troubleshooting

Authentication fails with "INVALID_CLIENT_CREDENTIALS" or HTTP 400 — the Consumer Key or Consumer Secret is incorrect. Double-check by copying them fresh from Setup > App Manager > your Connected App > Manage Consumer Details. Ensure the Connected App has "Enable OAuth Settings" checked and the api scope is listed. If you just created the Connected App, wait 2–10 minutes for Salesforce to propagate the settings before retrying.

Records fail with "REQUIRED_FIELD_MISSING: LastName" — the input records have no name, firstName, or lastName field. The actor defaults LastName to "Unknown" when no name data is found, but some org configurations override this. Check that your input records include a name field in any of the supported formats.

Records fail with "REQUIRED_FIELD_MISSING: Company" — Lead records require a Company value. The actor defaults to "Unknown Company" when no companyName or company field is found. If you see this error, your Salesforce org has a validation rule making the default value unacceptable. Add a company field to your input records.

Deduplication is not catching existing records — ensure skipDuplicates is true. Deduplication checks Salesforce's existing records by email for Leads/Contacts, or by name for Accounts. If your existing records used a different email format (uppercase vs lowercase), deduplication uses case-insensitive matching — but if emails differ entirely, duplicates will not be caught. The dedup query also does not paginate beyond 50 values per SOQL chunk — for very large batches with many pre-existing records, some may slip through.

Run is slow for large batches — the deduplication SOQL query runs before each batch of 200. For 1,000 leads this means 5 batch cycles, each with a SOQL query. This is expected behavior. Disable skipDuplicates if your dataset is known to be clean and you want maximum throughput.

Responsible use

  • This actor only writes data you explicitly provide — it does not scrape or collect data independently.
  • Ensure the personal data you push to Salesforce was collected with appropriate consent under GDPR, CAN-SPAM, CCPA, and other applicable data protection laws.
  • Do not use this actor to push data obtained through unauthorized scraping of protected or private systems.
  • Respect your Salesforce org's data governance policies and duplicate management rules.
  • For guidance on web scraping legality, see Apify's guide.

FAQ

How do I push leads to Salesforce from another Apify actor? — run the source actor (e.g. B2B Lead Gen Suite), copy the dataset ID from its run detail page, and paste it into the datasetId field of Salesforce Lead Pusher. The actor loads up to 5,000 records automatically with no export step.

Does Salesforce Lead Pusher update existing records or only create new ones? — it creates new records only. When skipDuplicates is true, records with a matching email or company name in Salesforce are skipped and logged as skipped_duplicate. True update-on-match (upsert) is not currently supported.

How many leads can I push to Salesforce in one run? — up to 5,000 from a dataset, or as many as you provide inline (subject to the maxLeads cap, default 500). Increase maxLeads up to 5,000 for larger batches. For datasets over 5,000 records, split across multiple runs.

Is it safe to test against my production Salesforce org? — use dry-run mode (dryRun: true) to validate field mapping without writing anything. For full live testing, use a Salesforce sandbox org — set salesforceLoginUrl to https://test.salesforce.com and use your sandbox username.

What Salesforce editions does this work with? — any Salesforce edition that supports Connected Apps and the REST API: Essentials, Professional (with API add-on), Enterprise, Unlimited, and Developer Edition. The Composite Collections API endpoint used is available in all REST API-enabled orgs on API version 59.0 and later.

How is this different from Salesforce's built-in data import wizard? — the import wizard requires manual CSV exports, column header matching, and manual deduplication. This actor runs on a schedule, accepts data directly from other Apify actors, handles field normalization automatically, and produces per-record audit output showing exactly what was created, skipped, or failed.

How much does it cost to push 1,000 leads to Salesforce? — $50.00 total ($0.05 per successfully created record). Dry-run runs, skipped duplicates, and failed records are not charged. Set a spending limit on the run if you want to cap costs — the actor stops cleanly when the limit is reached.

Can I push Salesforce Contacts instead of Leads? — yes, set objectType to Contact. Note that Contacts in Salesforce typically require an AccountId linking them to an existing Account. If your Contact records do not include an AccountId, they may fail with a validation error in orgs where AccountId is required. Use Lead for unqualified prospects.

Is it legal to push scraped contacts into Salesforce CRM? — legality depends on how the contact data was collected and the jurisdiction. In the EU, GDPR requires a lawful basis for processing personal data. In the US, CAN-SPAM and CCPA apply to marketing use. You are responsible for ensuring the data you push was collected lawfully. See Apify's web scraping legal guide for detailed guidance.

What happens if Salesforce rate limits the actor mid-run? — the actor detects REQUEST_LIMIT_EXCEEDED (HTTP 403) responses and automatically waits 10 seconds before retrying the batch once. If the retry also fails, the batch is marked as failed in the output. Most orgs have a daily API request limit of 100,000–1,000,000 — a single run pushing 500 records uses 3–6 API calls total.

Can I schedule this actor to run automatically? — yes. Use Apify's built-in scheduler to run daily, weekly, or at custom intervals. Combine with a scheduled scraping actor upstream and use datasetId chaining to keep Salesforce updated automatically without any manual steps.

How do I map a custom Salesforce field like LinkedIn_URL__c? — add it to the fieldMapping input: {"linkedinUrl": "LinkedIn_URL__c"}. The left side is the field name in your input data, the right side is the Salesforce API field name. Custom fields always end in __c. You can map as many custom fields as needed.

Help us improve

If you encounter issues, you can help us debug faster by enabling run sharing in your Apify account:

  1. Go to Account Settings > Privacy
  2. 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 Salesforce field mapping, enterprise integrations, or high-volume pipelines, reach out through the Apify platform.

How it works

01

Configure

Set your parameters in the Apify Console or pass them via API.

02

Run

Click Start, trigger via API, webhook, or set up a schedule.

03

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.

Last updated March 21, 2026

Ready to try Salesforce Lead Pusher?

Start for free on Apify. No credit card required.

Open on Apify Store