Social media scraping, business data, e-commerce via Apify actors. USE WHEN Twitter, Instagram, LinkedIn, TikTok, YouTube, Facebook, Google Maps, Amazon scraping.
Code-based replacement for token-heavy Apify MCP calls.
Progressive disclosure interface for web scraping and automation via the Apify platform. Filter data in code before returning to model context for massive token savings.
import { Apify } from '~/.claude/filesystem-mcps/apify'
const apify = new Apify(process.env.APIFY_TOKEN)
// Search for actors
const actors = await apify.search("instagram scraper")
// Call an actor
const run = await apify.callActor(actors[0].id, {
profiles: ["target"],
resultsLimit: 100
})
// Get and filter results IN CODE (key to token savings!)
const dataset = await apify.getDataset(run.defaultDatasetId)
const items = await dataset.listItems()
// Only filtered results reach model context
const relevant = items
.filter(item => item.likesCount > 1000)
.filter(item => item.timestamp > Date.now() - 86400000)
.slice(0, 10)
console.log(relevant) // Only 10 items vs 100+ unfiltered
Token Comparison:
MCP Approach (~57,000 tokens):
1. mcp__Apify__search-actors → 1,000 tokens result
2. mcp__Apify__call-actor → 1,000 tokens result
3. mcp__Apify__get-actor-output → 50,000 tokens unfiltered dataset
Code-First (~1,000 tokens - 98.2% reduction):
// All operations in code, filter before returning
const filtered = items.filter(...).slice(0, 10)
// Only 10 filtered items (500 tokens) reach model
Main client for interacting with Apify platform.
Constructor:
new Apify(token?: string)
token - Apify API token (defaults to process.env.APIFY_TOKEN)Methods:
search(query, options?)Search for actors by keyword.
const actors = await apify.search("instagram scraper", {
limit: 10,
offset: 0
})
Parameters:
query - Search keywordsoptions.limit - Max results (default: 10)options.offset - Skip results (default: 0)Returns: Array of Actor objects with id, name, title, description, stats
callActor(actorId, input, options?)Execute an actor.
const run = await apify.callActor("apify/instagram-scraper", {
profiles: ["target"],
resultsLimit: 100
}, {
memory: 2048,
timeout: 300
})
Parameters:
actorId - Actor ID or "username/actor-name"input - Actor-specific input configurationoptions.memory - Memory in MB (128, 256, 512, 1024, 2048, etc.)options.timeout - Timeout in secondsoptions.build - Build number or tagReturns: ActorRun object with run details and defaultDatasetId
getDataset(datasetId)Get dataset interface for reading/filtering data.
const dataset = await apify.getDataset(run.defaultDatasetId)
Returns: ApifyDataset instance
getRun(actorId, runId)Get run status.
const run = await apify.getRun(actorId, runId)
Returns: ActorRun object with current status
waitForRun(actorId, runId, options?)Wait for run to finish.
const finalRun = await apify.waitForRun(actorId, runId, {
waitSecs: 120
})
Returns: Final ActorRun object when complete
Interface for reading and filtering dataset results.
Key Concept: Filter in code BEFORE returning to model context!
Methods:
listItems(options?)List dataset items with pagination.
const items = await dataset.listItems({
offset: 0,
limit: 100,
fields: ['username', 'likesCount', 'text']
})
Parameters:
options.offset - Skip itemsoptions.limit - Max itemsoptions.fields - Include only these fieldsoptions.omit - Exclude these fieldsoptions.clean - Clean HTML/special charsReturns: Array of dataset items
getAllItems()Get all items (handles pagination automatically).
Warning: For large datasets, use listItems() with limit or filter in code.
const allItems = await dataset.getAllItems()
const filtered = allItems.filter(item => item.score > 0.8)
Returns: Array of all dataset items
filter(predicate)Helper to filter items by predicate.
const relevant = await dataset.filter(item =>
item.likesCount > 1000 &&
item.timestamp > Date.now() - 86400000
)
Parameters:
predicate - Filter function (item) => booleanReturns: Filtered items array
top(sortFn, limit)Helper to get top N items by sort function.
const topPosts = await dataset.top(
(a, b) => b.likesCount - a.likesCount,
10
)
Parameters:
sortFn - Sort comparison functionlimit - Number of items to returnReturns: Top N sorted items
// Find actor
const actors = await apify.search("web scraper")
const actor = actors[0]
// Execute actor
const run = await apify.callActor(actor.id, {
startUrls: ["https://example.com"],
maxPages: 50
})
// Wait for completion
await apify.waitForRun(actor.id, run.id)
// Get and filter results
const dataset = apify.getDataset(run.defaultDatasetId)
const items = await dataset.listItems({ limit: 100 })
// Filter in code - only relevant items reach model
const relevant = items
.filter(item => item.price < 100)
.filter(item => item.inStock)
.slice(0, 10)
const dataset = apify.getDataset(datasetId)
// Process in batches to avoid memory issues
let offset = 0
const limit = 1000
const results = []
while (true) {
const batch = await dataset.listItems({ offset, limit })
if (batch.length === 0) break
// Filter each batch
const filtered = batch.filter(item => item.relevant === true)
results.push(...filtered)
offset += limit
}
// Only filtered results go to model context
console.log(results)
const dataset = apify.getDataset(datasetId)
// Get top 10 posts by engagement
const topPosts = await dataset.top(
(a, b) => b.likesCount - a.likesCount,
10
)
// Only top 10 items (not entire dataset) reach model
console.log(topPosts)
# Required
APIFY_TOKEN=apify_api_xxxxx...
# Optional (uses defaults if not set)
APIFY_API_BASE_URL=https://api.apify.com/v2
Get your token from: https://console.apify.com/account/integrations
All types are exported from the main module:
import { Actor, ActorRun, DatasetOptions } from '~/.claude/filesystem-mcps/apify'
try {
const run = await apify.callActor(actorId, input)
await apify.waitForRun(actorId, run.id)
const finalRun = await apify.getRun(actorId, run.id)
if (finalRun.status !== 'SUCCEEDED') {
console.error('Actor run failed:', finalRun.status)
return
}
// Process results...
} catch (error) {
console.error('Apify error:', error.message)
}
# Run the Instagram scraper example
cd ~/.claude/filesystem-mcps/apify
bun run examples/instagram-scraper.ts
# Or use bun directly
bun examples/instagram-scraper.ts
Estimate your token savings:
function estimateTokens(data: any): number {
const str = JSON.stringify(data)
return Math.ceil(str.length / 4) // ~4 chars per token
}
// Before (MCP)
const allItems = await dataset.getAllItems() // 10,000 items
console.log('MCP tokens:', estimateTokens(allItems)) // ~50,000
// After (Code-First)
const filtered = allItems.filter(...).slice(0, 10) // 10 items
console.log('Code tokens:', estimateTokens(filtered)) // ~500
// Savings: 99% token reduction!
Use Code-First (this API):
Use MCP:
~/.claude/filesystem-mcps/README.mdSearch for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer