Connectors
/
PhantomBuster
Live · 38 tools

PhantomBuster Integration for AI Agents

PhantomBuster's API is well-documented. Wiring your agent into it correctly — with per-user API keys securely isolated, quota checked before launch, and container output streamed without blocking — is the part that takes longer than it should.
PhantomBuster
Live

Lead Generation

Automation

Status
Live
Tools
38 pre-built
Auth
API Key
Credential storage
Sandbox support

API Key Auth

No OAuth flow

Agent lifecycle control

Lead management

The real problem

Why this is harder than it looks

PhantomBuster is not a typical OAuth integration. It authenticates with a single API key that grants full access to an organization — launching agents, reading lead data, managing billing, and everything else. That simplicity is deceptive, because in a multi-tenant product it creates a storage and isolation problem most developers don't anticipate until they're in production.

Every user who connects PhantomBuster to your product has their own API key. You need a place to store those keys that is securely isolated per user — one customer's key must never be accessible when you're executing on behalf of another. Unlike OAuth, there's no token exchange or expiry lifecycle to manage, but the storage and retrieval problem is real: you need a vault that maps your internal user identifiers to PhantomBuster credentials, and that mapping has to be consistent across every tool call your agent makes.

Beyond storage, there are operational patterns specific to PhantomBuster that are easy to get wrong. Agents are asynchronous — phantombuster_agent_launch returns a container ID, not a result. You need polling logic that reads incremental output using fromOutputPos offsets, detects terminal states, and then fetches the structured result separately. Skip the quota check before launching and you'll hit a 429 mid-run with no partial result to recover from. PhantomBuster also has a plan-tiered API — AI completions require credits, branch management requires Team+, and CRM contact saving requires an active HubSpot integration — so your agent needs to reason about capability availability, not just call tools blindly.

Scalekit handles API key storage and per-user isolation, injects credentials on every request, and gives your agent structured tools for the full PhantomBuster API surface. Your code names a tool and passes parameters. The credential plumbing is not your problem.

Capabilities

What your agent can do with PhantomBuster

Once connected, your agent has 38 pre-built tools covering the full PhantomBuster platform:

  • Launch and monitor automation agents: start runs immediately or on a delay, stream incremental console output, stop running containers, and fetch structured results when execution completes
  • Manage the full agent lifecycle: create, configure, schedule, and delete agents; unschedule all at once for emergency stops; audit deleted agents for recovery planning
  • Save and query leads at scale: bulk-save up to 1,000 profiles per call to named lead lists, fetch with pagination, delete by ID — the full lead management surface
  • Check and respect resource limits: fetch org-level execution time, AI credit, and storage balances before launching to avoid mid-run quota failures
  • Run AI enrichment on scraped data: call PhantomBuster's AI completion service with structured response schemas to parse job titles, extract skills, or enrich raw profile output
Setup context

What we're building

This guide connects a lead generation agent to PhantomBuster — launching scraping automations, streaming results, and saving enriched profiles to lead lists on behalf of each user.

🤖
Example agent
Lead generation assistant launching PhantomBuster scrapers, monitoring runs, and saving profiles to lead lists on behalf of each user
🔑
Auth model
API Key auth — each user connects their own PhantomBuster account. identifier = your user ID
⚙️
Scalekit account
app.scalekit.com — Client ID, Secret, Env URL
🐍
Runtime
Python 3.8+ · Node.js also available
Setup

1 Setup: One SDK, One credential

Install the Scalekit SDK. The only credential your application manages is the Scalekit API key — no PhantomBuster secrets, no user API keys, nothing belonging to your customers.

pip install scalekit-sdk-python
npm install @scalekit-sdk/node
import scalekit.client import os from dotenv import load_dotenv load_dotenv() scalekit = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) actions = scalekit.actions
import { ScalekitClient } from '@scalekit-sdk/node'; import 'dotenv/config'; const scalekit = new ScalekitClient( process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET ); const actions = scalekit.actions;
Already have credentials?
Connected Accounts

2 Per-User Auth: Registering connected accounts

PhantomBuster uses API key authentication — there is no OAuth redirect flow. Each user provides their PhantomBuster API key once, and you register it with Scalekit. From that point on, Scalekit injects the key automatically on every tool call for that user.

scalekit.actions.upsert_connected_account( connection_name="phantombuster", identifier="user_pb_123", # your internal user ID credentials={"api_key": "your-users-phantombuster-api-key"} ) # Call this when a user connects their PhantomBuster account in your product's settings page
await actions.upsertConnectedAccount({ connectionName: "phantombuster", identifier: "user_pb_123", // your internal user ID credentials: { api_key: "your-users-phantombuster-api-key" } }); // Call this when a user connects their PhantomBuster account in your product's settings page

This call is idempotent — safe to call on key rotation or reconnection. Scalekit stores the API key encrypted in its vault and returns it on every subsequent tool call for this identifier.

No OAuth flow needed
PhantomBuster uses API key auth — there is no authorization link, redirect URI, or consent screen. Once you call upsertConnectedAccount, the user's account is immediately active. Scalekit injects the API key as the X-Phantombuster-Key header on every request. You never handle it in application code.
Get the API key from users at setup
Users find their PhantomBuster API key at phantombuster.com → Settings → API. Add a settings page in your product where users paste this key. Your backend calls upsertConnectedAccount to register it. The key grants full org access — communicate this clearly in your UI so users understand the permission scope before connecting.
Calling PhantomBuster

3 Calling PhantomBuster: What your agent writes

With the connected account registered, your agent calls PhantomBuster tools using execute_tool. Name the tool, pass parameters. Scalekit handles credential retrieval and request construction.

Launch an agent and stream output

The most common PhantomBuster workflow: launch an automation, poll for incremental output using fromOutputPos, then fetch the structured result when execution completes.

import time # Step 1: Launch the agent launch = actions.execute_tool( identifier="user_pb_123", tool_name="phantombuster_agent_launch", tool_input={ "id": "AGENT_ID", "output": "result-object" } ) container_id = launch["containerId"] # Step 2: Stream output incrementally until finished output_pos = 0 while True: output = actions.execute_tool( identifier="user_pb_123", tool_name="phantombuster_container_fetch_output", tool_input={"id": container_id, "fromOutputPos": output_pos} ) print(output.get("output", ""), end="", flush=True) output_pos = output.get("nextOutputPos", output_pos) if output.get("status") in ("finished", "error"): break time.sleep(3) # Step 3: Fetch the structured result result = actions.execute_tool( identifier="user_pb_123", tool_name="phantombuster_container_fetch_result", tool_input={"id": container_id} ) # Returns scraped profiles, leads, or whatever the script produces
// Step 1: Launch the agent const launch = await actions.executeTool({ identifier: "user_pb_123", toolName: "phantombuster_agent_launch", toolInput: { id: "AGENT_ID", output: "result-object" } }); const containerId = launch.containerId; // Step 2: Stream output incrementally until finished let outputPos = 0; while (true) { const output = await actions.executeTool({ identifier: "user_pb_123", toolName: "phantombuster_container_fetch_output", toolInput: { id: containerId, fromOutputPos: outputPos } }); process.stdout.write(output.output || ""); outputPos = output.nextOutputPos || outputPos; if (["finished", "error"].includes(output.status)) break; await new Promise(r => setTimeout(r, 3000)); } // Step 3: Fetch the structured result const result = await actions.executeTool({ identifier: "user_pb_123", toolName: "phantombuster_container_fetch_result", toolInput: { id: containerId } }); // Returns scraped profiles, leads, or whatever the script produces

Check resource quota before launching

Avoid mid-run failures by verifying execution time and credit balances before starting a scraping job. PhantomBuster enforces plan-level quotas — a 429 mid-run produces no partial result.

resources = actions.execute_tool( identifier="user_pb_123", tool_name="phantombuster_org_fetch_resources", tool_input={} ) exec_time = resources.get("executionTime", {}) if exec_time.get("remaining", 0) < 30: raise RuntimeError( f"Insufficient execution time: {exec_time.get('remaining')} min remaining." ) print(f"Execution time: {exec_time['remaining']} min remaining")
const resources = await actions.executeTool({ identifier: "user_pb_123", toolName: "phantombuster_org_fetch_resources", toolInput: {} }); const execTime = resources.executionTime || {}; if ((execTime.remaining || 0) < 30) { throw new Error(`Insufficient execution time: ${execTime.remaining} min remaining.`); } console.log(`Execution time: ${execTime.remaining} min remaining`);

Save scraped profiles as leads

After a run completes, bulk-save extracted profiles to a named lead list. Up to 1,000 leads per call — more efficient than looping phantombuster_leads_save.

# Fetch available lead lists lists = actions.execute_tool( identifier="user_pb_123", tool_name="phantombuster_lists_fetch_all", tool_input={} ) list_id = lists[0]["id"] # or filter by name # Bulk-save profiles from a completed run actions.execute_tool( identifier="user_pb_123", tool_name="phantombuster_leads_save_many", tool_input={ "listId": list_id, "leads": [ { "firstName": p.get("firstName"), "lastName": p.get("lastName"), "email": p.get("email"), "linkedinUrl": p.get("linkedinUrl"), "company": p.get("company"), "jobTitle": p.get("title"), "additionalFields": {"source": "phantombuster", "agentId": "AGENT_ID"} } for p in result ] } ) print(f"{len(result)} leads saved to list {list_id}")
// Fetch available lead lists const lists = await actions.executeTool({ identifier: "user_pb_123", toolName: "phantombuster_lists_fetch_all", toolInput: {} }); const listId = lists[0].id; // or filter by name // Bulk-save profiles from a completed run await actions.executeTool({ identifier: "user_pb_123", toolName: "phantombuster_leads_save_many", toolInput: { listId, leads: result.map(p => ({ firstName: p.firstName, lastName: p.lastName, email: p.email, linkedinUrl: p.linkedinUrl, company: p.company, jobTitle: p.title, additionalFields: { source: "phantombuster", agentId: "AGENT_ID" } })) } }); console.log(`${result.length} leads saved to list ${listId}`);

Enrich leads with AI completions

Use PhantomBuster's AI service to extract structured fields from raw scraper output — seniority levels, primary skills, or any other structured extraction. Requires AI credits (Pro+).

completion = actions.execute_tool( identifier="user_pb_123", tool_name="phantombuster_ai_completions", tool_input={ "model": "gpt-4o", "messages": [ { "role": "system", "content": "Extract seniority and primary skill from this LinkedIn headline. Return JSON only." }, { "role": "user", "content": "Senior Software Engineer at Acme Corp | React, TypeScript, GraphQL" } ], "responseSchema": { "type": "object", "properties": { "seniority": {"type": "string", "enum": ["junior", "mid", "senior", "lead", "exec"]}, "primarySkill": {"type": "string"} }, "required": ["seniority", "primarySkill"] } } ) # → {"seniority": "senior", "primarySkill": "React"}
const completion = await actions.executeTool({ identifier: "user_pb_123", toolName: "phantombuster_ai_completions", toolInput: { model: "gpt-4o", messages: [ { role: "system", content: "Extract seniority and primary skill from this LinkedIn headline. Return JSON only." }, { role: "user", content: "Senior Software Engineer at Acme Corp | React, TypeScript, GraphQL" } ], responseSchema: { type: "object", properties: { seniority: { type: "string", enum: ["junior", "mid", "senior", "lead", "exec"] }, primarySkill: { type: "string" } }, required: ["seniority", "primarySkill"] } } }); // → { seniority: "senior", primarySkill: "React" }
Framework wiring

4 Wiring into your agent framework

Scalekit integrates directly with LangChain. The agent decides which tools to call; Scalekit handles credential injection on every invocation. No API key plumbing in your agent logic.

from langchain_anthropic import ChatAnthropic from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from scalekit.langchain import get_tools pb_tools = get_tools( connection_name="phantombuster", identifier="user_pb_123" ) prompt = ChatPromptTemplate.from_messages([ ("system", "You are a lead generation assistant. Use the available tools to launch PhantomBuster agents, monitor runs, and manage lead lists."), MessagesPlaceholder("chat_history", optional=True), ("human", "{input}"), MessagesPlaceholder("agent_scratchpad"), ]) agent = create_tool_calling_agent(ChatAnthropic(model="claude-sonnet-4-6"), pb_tools, prompt) result = AgentExecutor(agent=agent, tools=pb_tools).invoke({ "input": "Check my execution time balance, launch the LinkedIn scraper agent, and save any new profiles to the Outbound Q2 lead list" })
import { ChatAnthropic } from "@langchain/anthropic"; import { AgentExecutor, createToolCallingAgent } from "langchain/agents"; import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts"; import { getTools } from "@scalekit-sdk/langchain"; const pbTools = getTools({ connectionName: "phantombuster", identifier: "user_pb_123" }); const prompt = ChatPromptTemplate.fromMessages([ ["system", "You are a lead generation assistant. Use the available tools to launch PhantomBuster agents, monitor runs, and manage lead lists."], new MessagesPlaceholder("chat_history", true), ["human", "{input}"], new MessagesPlaceholder("agent_scratchpad"), ]); const agent = await createToolCallingAgent({ llm: new ChatAnthropic({ model: "claude-sonnet-4-6" }), tools: pbTools, prompt }); const result = await AgentExecutor.fromAgentAndTools({ agent, tools: pbTools }).invoke({ input: "Check my execution time balance, launch the LinkedIn scraper agent, and save any new profiles to the Outbound Q2 lead list" });
Other frameworks supported
Tool reference

All 38 PhantomBuster tools

Grouped by capability. Your agent calls tools by name — no API wrappers to write.

Agent Management
phantombuster_agents_fetch_all
Retrieve all automation agents in the org — IDs, names, scripts, schedules, and current status
phantombuster_agent_fetch
Get full details of a specific agent by ID — script, schedule, launch type, arguments, and status
phantombuster_agent_save
Create or update an agent. Omit id to create; include id to update. Supports script, schedule, proxy, notifications, and execution limits
phantombuster_agent_delete
Permanently delete an agent and all its execution history. Irreversible
phantombuster_agent_launch
Launch an agent immediately. Returns a containerId for tracking progress via container tools
phantombuster_agent_launch_soon
Schedule an agent to launch in N minutes without setting up a full recurring schedule
phantombuster_agent_stop
Stop a running agent. Saves partial results collected up to that point
phantombuster_agents_fetch_deleted
Retrieve all deleted agents with deletion timestamps and actor — useful for audit trails
phantombuster_agents_unschedule_all
Disable automatic launch for every agent in the org. Use with caution — affects all scheduled agents at once
Container Management
phantombuster_containers_fetch_all
List all execution runs for a specific agent — IDs, status, exit codes, and timestamps. Paginated
phantombuster_container_fetch
Get a single container by ID. Optionally include output, result object, and runtime events in one call
phantombuster_container_fetch_output
Retrieve console output from a container. Use fromOutputPos to poll incrementally without re-reading prior output
phantombuster_container_fetch_result
Fetch the structured result object from a completed container — scraped profiles, extracted data, or exported records
phantombuster_container_attach
Attach to a running container and stream live console output in real-time
phantombuster_agent_fetch_output
Get the most recent container's output for an agent. Use fromOutputPos for incremental reads
phantombuster_org_fetch_running_containers
List all containers currently executing across the org — useful for monitoring live runs and detecting runaway agents
Lead Management
phantombuster_leads_save
Save a single lead to a list. Updates if a lead with the same identifier already exists
phantombuster_leads_save_many
Bulk-save up to 1,000 leads per call. More efficient than looping phantombuster_leads_save for post-run ingestion
phantombuster_leads_delete_many
Permanently delete up to 1,000 leads by ID. Irreversible
phantombuster_leads_fetch_by_list
Fetch leads from a list with pagination. Up to 1,000 per page
Lead Lists
phantombuster_lists_fetch_all
Retrieve all lead lists — IDs, names, lead counts, and creation timestamps
phantombuster_list_fetch
Retrieve a specific lead list by ID
phantombuster_list_delete
Permanently delete a lead list and all leads within it. Irreversible
Organization
phantombuster_org_fetch
Retrieve org details — plan, billing info, timezone, proxy config, and connected CRM integrations
phantombuster_org_fetch_resources
Get current resource usage and limits — execution time, AI credits, SERP credits, storage, and agent count
phantombuster_org_fetch_agent_groups
Retrieve agent groups and their ordering for dashboard organisation
phantombuster_org_save_agent_groups
Update agent groups and their ordering. Order is preserved exactly as provided
phantombuster_org_export_agent_usage
Export a CSV of agent usage metrics for up to 180 days. Pro+ for full range
phantombuster_org_export_container_usage
Export a CSV of container run metrics. Optionally filter to a specific agent
phantombuster_org_save_crm_contact
Save a contact to the connected HubSpot CRM. Requires HubSpot integration configured in PhantomBuster settings (Pro+)
Scripts
phantombuster_scripts_fetch_all
Retrieve all scripts for the current user — IDs, names, slugs, branches, and manifests
phantombuster_script_fetch
Get a specific script by ID including its argument schema. Source code available with Team+
Branch Management (Team+)
phantombuster_branches_fetch_all
Retrieve all script branches in the org — for managing staging vs. production script versions
phantombuster_branch_create
Create a new branch for developing and testing script changes without affecting production agents
phantombuster_branch_delete
Permanently delete a branch and all associated scripts. Irreversible
phantombuster_branch_release
Promote specified scripts from a branch to production
AI and Utilities
phantombuster_ai_completions
Run AI completions via PhantomBuster's service. Supports GPT-4o and GPT-4.1-mini with structured JSON response schemas. Requires AI credits (Pro+)
phantombuster_location_ip
Geolocate an IPv4 or IPv6 address — useful for validating proxy locations or enriching lead data
Connector notes

PhantomBuster-specific behavior

Agent execution is asynchronous — always poll for results
phantombuster_agent_launch returns a containerId, not a result. The agent runs asynchronously. Use phantombuster_container_fetch_output with fromOutputPos to stream output incrementally, checking the status field for "finished" or "error" to know when to stop. Never assume a launch call means the result is ready.
Plan tier gates specific tools
Not all tools are available on all plans. AI completions require AI credits (Pro+). Branch management requires Team+. CRM contact saving requires a HubSpot integration configured in PhantomBuster settings (Pro+). Calling a tool your plan doesn't support returns a permission error — check phantombuster.com/pricing before building workflows that depend on tier-gated tools.
API key grants full org access
A PhantomBuster API key gives complete access to the user's organization — launching agents, reading leads, managing billing. Communicate this clearly in your product's settings UI when asking users to connect. Users can find and regenerate their key at phantombuster.com → Settings → API.
Infrastructure decision

Why not build this yourself

The PhantomBuster API is documented. Storing an API key per user isn't technically hard. But here's what you're actually signing up for:

PROBLEM 01
Per-user API key storage that is securely isolated across tenants — one customer's PhantomBuster key must never be retrieved when executing on behalf of another
PROBLEM 02
Asynchronous execution patterns — launch, incremental output polling with byte offsets, terminal state detection, and structured result retrieval as a reliable multi-step workflow
PROBLEM 03
Plan-tiered API surface where tool availability varies by subscription — AI credits, branch access, and CRM tools each have different requirements that must be checked before invocation
PROBLEM 04
Quota management across execution time, AI credits, and storage — exceeded limits return 429s mid-run with no partial result, requiring proactive balance checks before every launch

That's one connector. Your agent product will eventually need Salesforce, GitHub, Gmail, Slack, and whatever else your customers ask for. Each has its own auth quirks and failure modes.

Scalekit maintains every connector. You maintain none of them.

Ready to ship

Automate leads, not auth

Free to start. Per-user API key isolation fully handled.
PhantomBuster
Live

Lead Generation

Automation

Status
Live
Tools
38 pre-built
Auth
API Key
Credential storage
Sandbox support