Design Rush Outreach Bot (Scraper + Automatic Message Sender)
Pricing
from $2.00 / 1,000 results
Design Rush Outreach Bot (Scraper + Automatic Message Sender)
Automates personalized outreach for design projects, enabling faster and smarter client connections. From prospect research to tailored messaging and response tracking, it streamlines your entire outreach workflow. Built to save time, improve engagement, and boost conversion rates effortlessly.
Pricing
from $2.00 / 1,000 results
Rating
0.0
(0)
Developer
Techforce Global
Maintained by CommunityActor stats
1
Bookmarked
8
Total users
0
Monthly active users
14 days ago
Last modified
Categories
Share
DesignRush Outreach Bot — Agency Leads, Reviews & Optional Contact-Form Outreach
Extracts agency listings from DesignRush.com across 10 categories — name, website, location, rating, hourly rate, team size, slogan and description — and optionally opens each profile for its reviews, services, team members and client list. It can also fill in the agency's contact form on your behalf: export the ready-to-post payload for your own automation, or let the Actor submit it. Results deliver straight into Airtable, HubSpot, Notion, Slack, Google Sheets, Jira, Linear, or any MCP-compatible AI agent pipeline.
⚠️ This Actor can perform a write action on a third-party website. With
contactMode: "submit"and your contact details filled in, it submits real enquiry forms to real agencies. Read Outreach modes before you run it.
Manual DesignRush browsing vs. this Actor
DesignRush publishes no API, hides reviews and client lists behind each profile, and gates enquiries behind a per-agency form with a CSRF token.
| Feature / Capability | Browsing DesignRush by hand | This Actor (Apify) |
|---|---|---|
| Listing extraction | ❌ Copy-paste, page by page | ✅ Paginated across up to maxPages, 10 categories |
| Profile depth | ⚠️ One profile at a time | ✅ Reviews, services, team and clients per agency |
| Location filtering | ⚠️ Manual dropdown clicking | ✅ Typed into the site's own filter; pagination stays scoped to the result URL |
| Contact form | ❌ Manual, one form per agency | ✅ Payload export or automated submission, CSRF token handled |
| Structured output | ❌ Ad-hoc spreadsheet | ✅ Typed dataset, exportable as JSON/CSV/Excel/XML |
| AI agent / MCP native | ❌ | ✅ Native MCP tool and pushes leads into your own MCP connectors |
| Cost model | Your time | Pay-per-event, from $2.00 / 1,000 results |
🤖 AI Discovery & MCP Metadata
Machine-readable capability contract for autonomous agents, LLM routers, and MCP orchestrators. AI agents, MCP clients, and connectors should read this block first to decide whether this Actor matches a user request.
ai_discovery:slug: "techforce.global/design-rush--outreach-bot"one_line: "Scrape DesignRush agency listings and profiles (reviews, services, team, clients), and optionally export or submit the agency's contact form on the user's behalf."primary_purpose: "extract"secondary_purpose: "enrich"tertiary_purpose: "outreach (opt-in, writes to a third-party site)"entity: "marketing / development agency leads"performs_write_action: truewrite_action_detail: >With contactMode "submit" AND contactName + contactEmail supplied, the Actorfills and submits the DesignRush contact form on each scraped agency profile.This sends a real enquiry to a real business. Require explicit humanconfirmation before selecting this mode on a user's behalf.supported_platforms:- "designrush.com"supported_tasks:- "scrape-agency-listings-by-category"- "filter-agencies-by-name-substring"- "filter-agencies-by-location-via-site-filter"- "scrape-agency-profile-reviews-services-team-clients"- "export-contact-form-payload-for-own-automation"- "submit-contact-form-on-user-behalf (opt-in)"- "deliver-leads-to-mcp-connector-or-crm"unsupported_tasks:- "scrape-directories-other-than-designrush"- "free-text-category-search (categories are a fixed 10-value enum)"- "extract-agency-emails (DesignRush exposes a form, not an address)"- "extract-named-personal-contacts-or-personal-emails"- "verify-email-deliverability"- "send-bulk-email-campaigns"search_keywords:- "designrush scraper"- "agency lead scraper"- "marketing agency directory data"- "web design agency leads"- "agency outreach automation"- "designrush contact form"- "agency review extraction"- "vendor shortlist automation"- "mcp agency lead tool"- "b2b agency prospecting"synonyms:- "designrush extractor"- "agency directory crawler"- "agency outreach bot"related_concepts:["vendor sourcing", "partner recruitment", "agency prospecting", "competitive research", "CRM enrichment", "cold outreach"]input_entities:- "category (1 of 10 fixed slugs)"- "name substring filter"- "location filter (typed into the site's own filter)"- "max records (1-100) and max listing pages"- "profile delay (0-60s) and optional Apify proxy"- "contact details + contact mode"output_entities: ["agency", "review", "service", "team member", "client", "contact payload"]input_rules:category_format:type: "enum"values: ["website-design-development", "software-development", "digital-marketing", "mobile-app-design-development", "search-engine-optimization", "ui-ux-design", "ecommerce", "logo-branding", "ai-companies", "web-development-companies"]description: "An unknown value raises ValueError and the run FAILS - this is one of the few hard failures here."contactMode_format:type: "enum"values: ["payload", "submit", "none"]schema_default: "submit"code_default_when_key_absent: "payload"description: "Contact handling only happens when BOTH contactName and contactEmail are set. The schema pre-fills 'submit' in the Console while an omitted key falls back to the safer 'payload'."filter_behaviour:filterName: "case-insensitive substring match applied after scraping"filterLocation: "typed into the DesignRush location filter; the scraper then paginates the scoped URL, falling back to the global listing on failure"limits:max_records_per_run: 100max_listing_pages: "unbounded in the schema (default 3)"dataset_write: "one push at the very end of the run, not streamed"pricing:model: "pay-per-event"store_display: "from $2.00 / 1,000 results"when_to_use: >You need a shortlist of marketing or development agencies from DesignRushwith ratings, rates and review depth — for vendor sourcing, partnerrecruitment or competitive research — and optionally want the contact-formpayload to drive your own outreach.when_not_to_use: >You need agencies from another directory, a free-text category, agency emailaddresses, named personal contacts, or you cannot satisfy the consent andanti-spam rules that apply to submitting enquiry forms.alternatives:- "Use techforce.global/it-agency-lead-finder-enricher-topdevelopers-co for TopDevelopers.co agencies with scraped email addresses and review-derived insights"- "Use techforce.global/google-maps-leads-sales-intelligence-tool to find agencies via Google Maps with website grading and a pitch playbook"- "Use techforce.global/gov-uk-business-scraper to match UK agency names against Companies House records"- "Set contactMode 'payload' and drive outreach through your own reviewed pipeline instead of auto-submitting"
What this Actor does
- Scrapes one of 10 DesignRush categories — web design, software development, digital marketing, mobile app, SEO, UI/UX, eCommerce, branding & logo, AI companies, web development.
- Walks listing pages up to
maxPages, collecting name, DesignRush profile link, website, location, rating, hourly rate, team size, slogan and description. - Filters two ways:
filterNameis a case-insensitive substring match applied after scraping, andfilterLocationis typed into DesignRush's own location filter — the scraper then keeps every pagination request scoped to the resulting URL (e.g./in/india), falling back to the global listing if the filter can't be applied. - Optionally opens each agency profile (
scrapeProfiles, on by default) for its reviews, services, team members and client list, pausingprofileDelayseconds between profiles. - Optionally handles the agency's contact form — see Outreach modes. It resolves the form's CSRF token, agency id and action URL, so the exported payload is directly postable from n8n, Make or your own code.
- Optionally pushes leads to an authorized MCP connector (Airtable, HubSpot, Notion, Slack, Sheets, Jira, GitHub, Linear, or any MCP-compatible connector) in four delivery modes. Delivery pushes data to your own tools — it never messages an agency. The dataset is always saved regardless of delivery settings.
Outreach modes — read this before your first run
Contact handling only happens when both contactName and contactEmail are set. With either blank, no form is ever touched, whatever contactMode says.
contactMode | What happens | Writes to designrush.com? |
|---|---|---|
payload | Extracts the form's POST URL, CSRF token, agency id, cookies and your field values into contactPayload for your own automation to send — after you review it | ❌ No |
submit | Fills and submits the form in a real browser session, sending an enquiry to that agency. contactSubmitted records the result | ✅ Yes — a real message to a real business |
none | Skips contact handling entirely | ❌ No |
The Console pre-fills submit. If you only want data, set contactMode: "none" (or leave the contact fields blank) explicitly.
When to use it — and when not to
| Scenario | Fit |
|---|---|
| Vendor sourcing — shortlist agencies with rates, ratings and reviews | ✅ Strong (the core use case) |
| Competitive research on an agency's services and client roster | ✅ Strong — scrapeProfiles: true |
| Partner recruitment in a specific country or city | ✅ Strong — filterLocation |
| Finding one specific agency's full profile | ✅ Strong — filterName + a higher maxPages |
| Building the outreach payload for your own reviewed pipeline | ✅ Strong — contactMode: "payload" |
| CRM / Airtable / HubSpot enrichment via connector | ✅ Strong (deliveryMode: "perAgency") |
| Automated enquiry submission at volume | ⚠️ Technically supported — but see Compliance first; this is regulated outreach, not scraping |
| Agency email addresses | ❌ DesignRush exposes a form, not an address — use TopDevelopers Scraper for scraped emails |
| A category outside the 10 fixed slugs | ❌ Unknown category fails the run |
| Named personal contacts (CEO/CTO email) | ❌ Not supported |
| More than 100 agencies per run | ⚠️ maxRecords ceiling is 100 — split across runs |
| Directories other than DesignRush | ❌ Not supported |
| Bulk email campaigns | ❌ Not supported — this fills one enquiry form per agency, nothing more |
⚡ Execution Rules (Avoid Common Agent Failures)
contactModedefaults differ between the Console and the API. The schema pre-fillssubmit; the code falls back topayloadwhen the key is absent. So a Console run with contact details filled in sends real enquiries, while an API payload that omitscontactModeonly exports the payload. Always sendcontactModeexplicitly — and treatsubmitas an action requiring human sign-off.- No contact handling without both
contactNameandcontactEmail. If either is blank,contactPayloadisnullandcontactSubmittedisfalseregardless ofcontactMode. - An unknown
categoryfails the run withValueError: Unknown category '<x>'. It is one of the very few hard failures here — everything else degrades gracefully. Use the exact slugs from the 10-value enum. maxRecordscounts records after filtering (1–100). With afilterNameorfilterLocationset you usually need to raisemaxPageswell above its default of 3, or the run finishes short simply because it never looked far enough.maxPageshas no upper bound in the schema. A large value on a broad category is a long, expensive run — set it deliberately.filterNameis a substring match applied after scraping, so it cannot make the scraper find an agency on a page it never visited. Pair it with a highermaxPages.filterLocationdrives the site's own filter and can silently fall back. If the dropdown suggestion can't be resolved, the run continues against the global listing — check the log lineLocation filter : …to confirm what was actually applied.- Missing values are the string
"N/A", nevernullor absent, for every listing field. - The dataset is written once, at the end of the run. Unlike the Google-Maps family, results are not streamed — a run that dies mid-scrape leaves no partial dataset.
scrapeProfiles: falsestill emits the profile keys —reviews,services,team,clientsare present but empty, andcontactPayloadisnull. Absent-vs-empty is not a signal here.deliveryModedefaults toperAgency, notnone. With a connector selected, a 100-agency run makes 100 connector calls. For dataset-only runs leavemcpConnectorempty or setdeliveryMode: "none".- The proxy is off by default and only applied when you enable it.
proxyConfigurationis passed to the browser only whenuseApifyProxyis true; otherwise the run uses a direct connection. Turn it on if DesignRush starts serving empty pages.
dependencies:- rule: "contact handling requires BOTH contactName and contactEmail"on_violation: "contactPayload stays null and contactSubmitted stays false"- rule: "contactMode 'submit' writes to designrush.com"note: "requires explicit human intent; prefer 'payload' for agent-driven runs"- rule: "an unknown category raises ValueError and fails the run"on_violation: "the log lists every valid category slug"- rule: "filterName/filterLocation need a higher maxPages to find matches"on_violation: "the run ends short of maxRecords with no error"- rule: "the dataset is pushed once at the end of the run"on_violation: "a crash mid-run leaves an empty dataset"- rule: "delivery requires mcpConnector AND mcpTool"on_violation: "delivery step is skipped with a warning; the dataset is still written in full"- rule: "mcpArguments must reference {message} for the rendered template to appear anywhere"on_violation: "message body is empty; the tool is still called"- rule: "mcpConnector only resolves when the Actor runs on the Apify platform"on_violation: "local runs log 'APIFY_MCP_PROXY_URL is not set' and skip delivery; the dataset is unaffected"authentication:actor_input: noneplatform: "Apify API token required for API / SDK / MCP invocation"target_site: "no DesignRush account required; the contact form is the site's public enquiry form"
📥 Input Contract
.actor/input_schema.json is authoritative — if any table on this page disagrees with the schema files, the schema files win. The one place they diverge is the contactMode default (see Rule 1).
Scraping Parameters
| Field | Type | Required | Default | Allowed Values / Format | Example |
|---|---|---|---|---|---|
category | string (enum) | ⬜ No | website-design-development | 10 exact slugs (see below) — unknown values fail the run | ai-companies |
filterName | string | ⬜ No | "" | Case-insensitive substring, applied after scraping | Prismetric |
filterLocation | string | ⬜ No | "" | Typed into DesignRush's location filter | India |
maxRecords | integer | ⬜ No | 10 | 1–100, counted after filtering | 100 |
maxPages | integer | ⬜ No | 3 | 1+ — no upper bound; raise it when filtering | 15 |
scrapeProfiles | boolean | ⬜ No | true | Adds reviews, services, team, clients per agency | false |
profileDelay | number | ⬜ No | 2.0 | 0–60 seconds between profile visits — only used when scrapeProfiles is on | 3.5 |
proxyConfiguration | object | ⬜ No | { "useApifyProxy": false } | Apify proxy editor object; applied only when useApifyProxy is true | { "useApifyProxy": true } |
Outreach Parameters
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
contactMode | string (enum) | ⬜ No | submit in the Console, payload when the key is omitted | payload · submit · none |
contactName | string | ⚠️ For any contact handling | "" | Your name — required together with contactEmail |
contactEmail | string | ⚠️ For any contact handling | "" | Your email — required together with contactName |
contactCompany | string | ⬜ No | "" | Your company name |
contactPhone | string | ⬜ No | "" | Your phone |
contactWebsite | string | ⬜ No | "" | Your website |
contactMessage | string | ⬜ No | a generic "I'd like to discuss a potential project" line | Rewrite this. A generic message sent at volume is what gets senders blocked |
sendCopy | boolean | ⬜ No | false | Ask DesignRush to copy you on the enquiry |
newsletter | boolean | ⬜ No | false | Ticks the newsletter opt-in box on the form |
Category reference — all 10 slugs
| Slug | Console label |
|---|---|
website-design-development | Web Design Companies |
software-development | Software Development |
digital-marketing | Digital Marketing |
mobile-app-design-development | Mobile App Development |
search-engine-optimization | SEO Agencies |
ui-ux-design | UI/UX Design |
ecommerce | eCommerce Development |
logo-branding | Branding & Logo |
ai-companies | AI Companies |
web-development-companies | Web Development |
Each maps to https://www.designrush.com/agency/<slug>.
Examples
Data only — no contact form touched:
{"category": "ai-companies","maxRecords": 50,"maxPages": 8,"scrapeProfiles": true,"contactMode": "none","deliveryMode": "none"}
Fast listing sweep — no profile visits:
{"category": "digital-marketing","maxRecords": 100,"maxPages": 12,"scrapeProfiles": false,"contactMode": "none","deliveryMode": "none"}
Find one agency by name — note the raised maxPages:
{"category": "website-design-development","filterName": "Prismetric","maxRecords": 5,"maxPages": 20,"contactMode": "none","deliveryMode": "none"}
Outreach payload for your own reviewed pipeline (no submission):
{"category": "ui-ux-design","filterLocation": "India","maxRecords": 25,"maxPages": 10,"contactMode": "payload","contactName": "Your Name","contactEmail": "you@yourcompany.com","contactCompany": "Your Company","contactWebsite": "https://yourcompany.com","contactMessage": "Specific, relevant, non-generic message referencing their work.","deliveryMode": "none"}
MCP Delivery Configuration (Optional)
Delivery sends your results to your own tools. It never contacts an agency — that is contactMode's job alone.
| Parameter | Type | Default | Description |
|---|---|---|---|
mcpConnector | string | "" | Authorized MCP connector on your Apify account (Airtable, HubSpot, Notion, Slack, Sheets, Jira, GitHub, Linear, …). Leave empty for dataset-only runs. |
deliveryMode | enum | perAgency | perAgency (one call per agency) · chunked (split a long list across calls) · summary (one digest) · none. |
mcpTool | string | "" | Tool name on the connector: create_record, send_message, create_page, create_issue. Run once with a connector selected — the log lists the connector's available tools. |
mcpArguments | object | {} | Arguments passed to the tool. String leaves support {placeholders}. |
mcpMessageTemplate | string | "" | Template rendered and exposed to mcpArguments as {message}. |
Placeholders by mode:
| Mode | Placeholders |
|---|---|
perAgency | {name}, {website}, {profileLink}, {location}, {rating}, {hourlyRate}, {employees}, {slogan}, {description}, {services}, {clients}, {reviewCount}, {serviceCount}, {teamCount}, {clientCount}, {contactSubmitted}, {agency} (formatted multi-line block), {message} |
summary | {agencyCount}, {category}, {agencies} (every agency as a block), {message} |
chunked | the above, plus {part} and {partCount} — and {agencies} holds one part |
"N/A" values render as empty strings, so a template never posts a literal N/A. Chunked delivery truncates each agency block at ~1,800 characters and groups blocks into parts under ~72,000 characters, so Notion-style block and timeout caps are never hit.
One Airtable/CRM record per agency:
{"category": "software-development","maxRecords": 60,"maxPages": 10,"contactMode": "none","mcpConnector": "<your-authorized-airtable-connector>","deliveryMode": "perAgency","mcpTool": "create_record","mcpArguments": {"fields": {"Agency": "{name}","Location": "{location}","Rating": "{rating}","Hourly rate": "{hourlyRate}","Team size": "{employees}","Website": "{website}","Profile": "{profileLink}","Services": "{services}"}}}
One Slack digest for the whole run:
{"category": "search-engine-optimization","maxRecords": 40,"contactMode": "none","mcpConnector": "<your-authorized-slack-connector>","deliveryMode": "summary","mcpTool": "send_message","mcpArguments": { "channel": "#agency-shortlist", "text": "{message}" },"mcpMessageTemplate": "{agencyCount} {category} agencies:\n\n{agencies}"}
Chunked into Notion pages for a long list:
{"category": "ecommerce","maxRecords": 100,"maxPages": 15,"contactMode": "none","mcpConnector": "<your-authorized-notion-connector>","deliveryMode": "chunked","mcpTool": "notion-create-pages","mcpArguments": {"parent": { "page_id": "<your-page-id>" },"pages": [{"properties": { "title": "eCommerce agencies (part {part}/{partCount})" },"content": "{agencies}"}]}}
📤 Output Contract & Data Structure
Storage: Apify Dataset (one JSON object per agency), written in a single push at the end of the run.
Pagination: limit & offset on the dataset items endpoint.
Duplicates: one record per agency within a run. Cross-run deduplication is the consumer's responsibility — use profileLink as the key.
Listing fields — always present
| Field | Type | Meaning |
|---|---|---|
name | string | Agency name. "N/A" when the card had none |
profileLink | string | DesignRush profile URL — use as the dedupe key |
website | string | The agency's own website |
location | string | Location as displayed on the card |
rating | string | Rating as a string, not a number |
hourlyRate | string | Rate band as displayed — e.g. "$50 - $99 / hr" |
employees | string | Team-size band as displayed |
slogan | string | Tagline from the card |
description | string | Short description from the card |
Every one of these uses "N/A" as its missing-value sentinel — never null, never an absent key.
Profile fields — always present, populated when scrapeProfiles is on
| Field | Type | Meaning |
|---|---|---|
reviews | array | Client reviews from the profile page |
services | array | Services listed on the profile |
team | array | Team members listed on the profile |
clients | array | Notable clients listed on the profile |
With scrapeProfiles: false — or when a profile has no URL or fails to load — these are present but empty arrays.
Outreach fields
| Field | Type | Meaning |
|---|---|---|
contactPayload | object | null | Only in payload mode: postUrl, agencyId, cookies and a payload object carrying the CSRF _token, valid_from, previous_url and your field values — ready to POST |
contactSubmitted | boolean | true only when submit mode actually completed a submission for that agency |
Example output item
{"name": "Northwind Digital","profileLink": "https://www.designrush.com/agency/profile/northwind-digital","website": "https://northwinddigital.com","location": "Austin, TX, United States","rating": "4.9","hourlyRate": "$100 - $149 / hr","employees": "50 - 249","slogan": "Design that converts","description": "Full-service web design and conversion optimisation studio.","reviews": [{"reviewer": "A. Fitzgerald","rating": "5","text": "Rebuilt our storefront and doubled checkout completion."}],"services": [{ "name": "Web Design" }, { "name": "Conversion Optimisation" }],"team": [{ "name": "J. Okafor", "role": "Design Director" }],"clients": [{ "name": "Regional Bank Co." }],"contactPayload": null,"contactSubmitted": false}
Example contactPayload — payload mode
{"contactPayload": {"postUrl": "https://www.designrush.com/submit/agency-contact/save","agencyId": "12345","cookies": "XSRF-TOKEN=…; designrush_session=…","payload": {"_token": "…","agency_id": "12345","valid_from": "…","previous_url": "https://www.designrush.com/agency/profile/northwind-digital","name": "Your Name","email": "you@yourcompany.com","company_name": "Your Company","phone": "","website": "https://yourcompany.com","message": "Specific, relevant, non-generic message referencing their work.","newsletter": "","send_copy": ""}}}
The _token and cookies are session-bound — post the payload promptly or re-run to refresh them.
What a successful run looks like
{"status": "SUCCEEDED","defaultDatasetId": "<datasetId>","stats": { "itemCount": 42 }}
itemCount below maxRecords usually means the filters matched fewer agencies within maxPages — raise maxPages before assuming a bug. itemCount: 0 on a SUCCEEDED run means nothing survived the filters. A FAILED run with Unknown category in the log is an invalid category slug.
▶️ Invocation & Integration
Lifecycle: Discover → Understand → Configure → Execute → Retrieve → Validate. Authenticate every call with Authorization: Bearer <APIFY_TOKEN>.
Apify Console
Open the Actor → Input tab → pick a Category → set Total records and Max pages → decide on Scrape Profile Pages → set Contact Mode deliberately (it pre-fills submit) → (optional) pick an MCP connector, tool and template → Start → export from the Dataset tab (JSON, CSV, Excel, XML).
Model Context Protocol (MCP)
claude mcp add --transport http apify \"https://mcp.apify.com?tools=techforce.global/design-rush--outreach-bot"
Python (apify-client)
import osfrom apify_client import ApifyClientclient = ApifyClient(os.getenv("APIFY_TOKEN"))run = client.actor("techforce.global/design-rush--outreach-bot").call(run_input={"category": "ai-companies","maxRecords": 50,"maxPages": 10,"scrapeProfiles": True,"contactMode": "none", # send this explicitly - the Console pre-fills "submit""deliveryMode": "none",})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(f"{len(items)} agencies")# Every listing field uses "N/A" as its missing-value sentinel.rated = [i for i in items if i.get("rating", "N/A") != "N/A"]print(f"{len(rated)} with a rating")for agency in rated[:5]:print(agency["name"],"|", agency.get("location"),"|", agency.get("hourlyRate"),"|", f'{len(agency.get("reviews", []))} reviews',)
JavaScript / TypeScript (apify-client)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('techforce.global/design-rush--outreach-bot').call({category: 'digital-marketing',filterLocation: 'India',maxRecords: 100,maxPages: 15,scrapeProfiles: false, // listing-only sweep, much fastercontactMode: 'none',deliveryMode: 'none',});const { items } = await client.dataset(run.defaultDatasetId).listItems();const withSite = items.filter((i) => i.website !== 'N/A');console.log(`${items.length} agencies, ${withSite.length} with a website`);
cURL — synchronous (returns items directly; 300s limit)
curl -X POST \-H 'Content-Type: application/json' \-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \-d '{"category":"ui-ux-design","maxRecords":20,"maxPages":5,"scrapeProfiles":false,"contactMode":"none","deliveryMode":"none"}' \'https://api.apify.com/v2/acts/techforce.global~design-rush--outreach-bot/run-sync-get-dataset-items'
Use the async pattern below whenever scrapeProfiles is on — a profile visit plus profileDelay per agency adds up fast.
cURL — asynchronous with a spend cap (recommended for production)
# 1. Start execution with a hard spend limitcurl -X POST -H 'Content-Type: application/json' \-H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \-d '{"category":"ecommerce","maxRecords":100,"maxPages":15,"scrapeProfiles":true,"contactMode":"none","deliveryMode":"none"}' \'https://api.apify.com/v2/acts/techforce.global~design-rush--outreach-bot/runs?maxTotalChargeUsd=1.00'# 2. Pollcurl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \'https://api.apify.com/v2/actor-runs/<runId>'# 3. Retrieve when SUCCEEDEDcurl -H 'Authorization: Bearer <YOUR_APIFY_TOKEN>' \'https://api.apify.com/v2/datasets/<DATASET_ID>/items?clean=true&format=json&limit=1000&offset=0'
⚠️ Autonomous Agent Error Handling & Resolution Matrix
| Error Code | Detection Condition | Underlying Cause | Deterministic Agent Action |
|---|---|---|---|
AUTH_INVALID | HTTP 401 | Missing or malformed APIFY_TOKEN | Abort & Prompt User: request a valid API token. |
RATE_LIMITED | HTTP 429 | Apify API rate / concurrency limits | Retry: exponential backoff (2s, 4s, 8s). |
SYNC_TIMEOUT | HTTP 408 on the sync endpoint | Run exceeded the 300s ceiling — likely with scrapeProfiles: true | Reconfigure: switch to async POST /runs + polling. |
UNKNOWN_CATEGORY | FAILED, log Unknown category '<x>'. Available: […] | category outside the 10-slug enum | Modify Input: copy a slug from the list in the same log line. |
UNINTENDED_OUTREACH | contactSubmitted: true on items you expected to be data-only | contactMode was submit (the Console default) with contact details filled in | Stop & Escalate: real enquiries were sent. Set contactMode: "none" and inform the user. |
NO_CONTACT_HANDLING | contactPayload: null and contactSubmitted: false despite contactMode: "payload" | contactName or contactEmail was blank | Modify Input: supply both fields. |
SHORT_RUN | itemCount well below maxRecords, no error | Filters matched fewer agencies inside maxPages | Reconfigure: raise maxPages; maxRecords counts post-filter records. |
FILTER_FELL_BACK | Results ignore your location | The site's location filter couldn't be resolved; the run used the global listing | Verify: read the Location filter : log line; retry with a simpler place name. |
EMPTY_RESULTS | SUCCEEDED, itemCount: 0 | Nothing survived filterName / filterLocation | Modify Input: relax the filters or raise maxPages. |
NO_PARTIAL_DATA | FAILED with an empty dataset | Results are pushed once at the end — a mid-run crash saves nothing | Retry with a lower maxRecords / maxPages to shorten the run. |
NA_SENTINEL | Fields contain the literal "N/A" | That is the missing-value sentinel for every listing field | Fix Consumer: compare against "N/A", not None. |
EMPTY_PROFILE_BLOCKS | reviews / services / team / clients are [] everywhere | scrapeProfiles: false, or profiles failed / had no URL | Modify Input: set scrapeProfiles: true; check the log for profile failures. |
STALE_PAYLOAD | Posting a saved contactPayload is rejected | _token and cookies are session-bound and expire | Re-run to mint a fresh payload, then post promptly. |
DELIVERY_SKIPPED | Log no tool name was provided | mcpConnector set but mcpTool empty | Modify Input: set mcpTool; the dataset is already saved. |
DELIVERY_TOOL_UNKNOWN | Log Tool 'x' is not available on this connector | Wrong tool name for that connector | Modify Input: pick a name from the Available tools: list in the same log line. |
DELIVERY_EMPTY | Connector called, body empty | mcpArguments omitted the {message} placeholder | Modify Input: map {message} inside mcpArguments. |
DELIVERY_FLOOD | Hundreds of connector calls / connector rate limits | deliveryMode defaults to perAgency | Reconfigure: use summary or chunked. |
MCP_PROXY_MISSING | Log APIFY_MCP_PROXY_URL is not set | Running locally instead of on the platform | Reconfigure: apify push and run on the platform. |
CHARGE_LIMIT | Run aborted before maxRecords reached | maxTotalChargeUsd spend threshold reached | Prompt User: confirm a higher spend cap. |
⚠️ Verify before publishing: the HTTP status rows reflect standard Apify API behavior; every log-line and field condition above is taken from this Actor's source. Re-confirm the
408/429rows against current platform behavior if you depend on them for automated retry logic.
🗣️ Natural Language → Actor Mapping
| User says | Intent | Constructed Actor input |
|---|---|---|
| "Find web design agencies on DesignRush" | Vendor sourcing | {"category":"website-design-development","maxRecords":50,"maxPages":8,"contactMode":"none"} |
| "List AI companies with their rates" | Rate benchmarking | {"category":"ai-companies","maxRecords":100,"contactMode":"none"} then read hourlyRate |
| "SEO agencies in India" | Geographic slice | {"category":"search-engine-optimization","filterLocation":"India","maxPages":12,"contactMode":"none"} |
| "Just the listings, quickly" | Fast sweep | {"scrapeProfiles":false,"contactMode":"none"} |
| "What services and clients does this agency have?" | Profile depth | {"filterName":"<agency>","scrapeProfiles":true,"maxPages":20,"contactMode":"none"} |
| "Which agencies have the best reviews?" | Quality ranking | {"scrapeProfiles":true,"contactMode":"none"} then rank on reviews |
| "Find a specific agency called X" | Single lookup | {"filterName":"X","maxPages":20,"contactMode":"none"} |
| "Give me the contact-form payloads so my workflow can send them" | Payload export | {"contactMode":"payload","contactName":"…","contactEmail":"…","contactMessage":"…"} |
| "Push these agencies into Airtable" | CRM delivery | {"mcpConnector":"airtable","deliveryMode":"perAgency","mcpTool":"create_record"} |
| "Post an agency shortlist to Slack" | Digest delivery | {"mcpConnector":"slack","deliveryMode":"summary","mcpTool":"send_message"} |
| "Save 100 agencies into Notion without it timing out" | Chunked delivery | {"deliveryMode":"chunked","mcpTool":"notion-create-pages"} with {part}/{partCount} |
| "Message every agency for me" | Automated outreach | ⚠️ Confirm with the user first. contactMode: "submit" sends real enquiries — see Compliance |
| "Get me each agency's email address" | Email discovery | ❌ DesignRush exposes a form, not an address → TopDevelopers Scraper |
| "Find agencies on Clutch or GoodFirms" | Other directory | ❌ Out of scope — DesignRush only |
| "Send a bulk email campaign to these agencies" | Bulk email | ❌ Out of scope — this fills one enquiry form per agency, nothing more |
Should NOT route here: directories other than DesignRush (Clutch, GoodFirms, TopDevelopers) · agency email addresses · named personal contacts · bulk email campaigns · free-text categories outside the 10 slugs · any unattended submit-mode run an agent chose on its own.
🧭 Agent Execution & Routing Logic
[Input User Query]│▼1. Target is the DesignRush directory? NO → Route to the right platform Actor│ YES▼2. Does the request map to one of the 10 categories? NO → Abort (an unknown slug FAILS the run)│ YES▼3. Does the user want MESSAGES SENT to agencies?├── NO (data only) → contactMode "none" ← default choice for agent-driven runs├── MAYBE / build-first → contactMode "payload" (exports a postable payload, sends nothing)└── YES, explicitly → STOP. Get human confirmation, a specific non-generic contactMessage,and confirm the anti-spam basis. Only then contactMode "submit".▼4. Need reviews / services / team / clients? YES → scrapeProfiles true (slower; use async invocation)│ NO → scrapeProfiles false▼5. Filtering by name or location? YES → raise maxPages well above 3│ (maxRecords counts POST-filter records)▼6. Volume > 100 agencies? YES → Partition across runs (maxRecords ceiling is 100)▼7. Deliver to a connector? YES → mcpConnector + mcpTool + {message}│ (delivery writes to YOUR tools, never to an agency)│ NO → set deliveryMode "none" (it defaults to perAgency)▼[Execute Apify Actor]│├──► status == "SUCCEEDED" ──► itemCount 0? → filters too tight, or maxPages too low│ else → dedupe on profileLink; treat "N/A" as missing;│ verify contactSubmitted matches what the user authorised└──► status == "FAILED" ──► "Unknown category" = bad slug; otherwise expect an EMPTY dataset(results are pushed only at the end of a run)
💰 Cost Control & Pricing Transparency
- Pay-per-event pricing: from $2.00 per 1,000 results on the entry tier, discounted at higher Apify subscription tiers. No monthly subscription.
- Autonomous spend caps: pass
maxTotalChargeUsdas a query parameter on the run endpoint for a hard per-execution ceiling.
| Agencies returned | Cost at $2.00 / 1,000 |
|---|---|
| 10 agencies (default run) | $0.02 |
| 50 agencies | $0.10 |
| 100 agencies (per-run ceiling) | $0.20 |
| 1,000 agencies (10 runs) | $2.00 |
Platform usage is billed on top at your plan's rates. This Actor drives a real browser, so scrapeProfiles: true — one profile page plus a profileDelay pause per agency — is by far the biggest driver of compute-unit consumption. A listing-only sweep is dramatically cheaper in platform usage even though the per-result price is identical.
Cost levers: run scrapeProfiles: false when you only need the listing fields; keep maxRecords and maxPages tight (a high maxPages on a broad category is a long run whether or not it finds matches); and set maxTotalChargeUsd.
⚠️ Verify before publishing: the $2.00 / 1,000 figure is taken from the Store listing, which describes a pay-per-event model. This repo contains no
pay_per_event.jsonand the code makes noActor.charge()calls, so billing is configured entirely on the Store listing — confirm the live event configuration before publishing.
🔍 Companion machine-readable files
| File | Purpose |
|---|---|
.actor/actor.json | Identity, version, input/output/dataset wiring |
.actor/input_schema.json | Authoritative typed input contract — 10-slug category enum, filters, maxRecords (1–100), maxPages, profile toggle, contact fields, contactMode enum, deliveryMode enum |
.actor/dataset_schema.json | Output field types and the Console table view |
.actor/output_schema.json | Declares where results are stored |
my_actor/main.py | Input handling, category resolution, and the delivery hand-off |
my_actor/categories.py | The 10 category slug → DesignRush URL map |
my_actor/scraper.py | Listing pagination, location filtering, profile scraping, contact-form payload extraction and submission |
my_actor/delivery.py | MCP connector delivery modes and {placeholder} rendering |
my_actor/connector.py | MCP connector session handling through the Apify MCP Proxy |
Note: this Actor has no pay_per_event.json — billing is configured entirely on the Store listing.
If any table on this page disagrees with the schema files, the schema files win — with the single exception of contactMode, where the schema pre-fills submit while the code's absent-key fallback is payload.
🛠️ Troubleshooting
| # | Symptom you see | Most likely cause | Fix |
|---|---|---|---|
| 1 | Enquiries were sent to agencies and you didn't expect it | contactMode was submit (the Console default) with contact details filled in | Set contactMode: "none" or "payload". Real messages went out — tell whoever owns the relationship. |
| 2 | FAILED — Unknown category '<x>' | category outside the 10-slug enum | Copy an exact slug; the log lists every valid one. |
| 3 | contactPayload is null in payload mode | contactName or contactEmail was blank | Supply both — contact handling needs the pair. |
| 4 | Far fewer agencies than maxRecords | Filters matched fewer inside maxPages — maxRecords counts post-filter | Raise maxPages (default 3 is low when filtering). |
| 5 | Location filter appears ignored | The site filter couldn't be resolved; the run fell back to the global listing | Check the Location filter : log line; try a simpler place name. |
| 6 | filterName found nothing | It is a post-scrape substring match, not a site search | Raise maxPages so the agency's page is actually visited. |
| 7 | Empty dataset after a failed run | Results are pushed once at the end — nothing is streamed | Shorten the run (maxRecords / maxPages) and retry. |
| 8 | Fields contain "N/A" | That is the missing-value sentinel for every listing field | Compare against "N/A", not None. |
| 9 | reviews / services / team / clients are all [] | scrapeProfiles: false, or the profiles failed / had no URL | Set scrapeProfiles: true and check the log for profile errors. |
| 10 | Posting a saved contactPayload is rejected | _token and cookies are session-bound and expire | Re-run to mint a fresh payload and post promptly. |
| 11 | Run is very slow | One profile page plus a profileDelay pause per agency | Use scrapeProfiles: false, lower maxRecords, or lower profileDelay — but don't hammer the site. |
| 12 | HTTP 408 on run-sync-get-dataset-items | The synchronous endpoint has a hard 300-second ceiling | Use async: POST /runs → poll → fetch dataset. |
| 13 | Blank or empty listing pages | DesignRush served an empty page to the container IP | Enable Use Apify Proxy under Network, then re-run. |
| 14 | Hundreds of connector calls / connector rate-limited | deliveryMode defaults to perAgency | Switch to summary or chunked. |
| 15 | Notion rejects or truncates a long list | Single-call payload exceeded block/timeout caps | Use deliveryMode: "chunked" with {part}/{partCount} in the title. |
| 16 | Slack / Airtable / Notion received nothing | Delivery needs both mcpConnector and mcpTool | Set both. The dataset is still written in full. |
| 17 | Connector fired but the message body is empty | mcpArguments did not reference {message} | Map {message} in mcpArguments and populate mcpMessageTemplate. |
| 18 | Log: APIFY_MCP_PROXY_URL is not set | You ran locally; connectors only resolve on the platform | Deploy with apify push and run on the platform. |
| 19 | HTTP 401 / 403 | Missing, expired, or malformed APIFY_TOKEN | Regenerate in Apify Console → Settings → API & Integrations. |
| 20 | HTTP 429 | Apify account concurrency / rate limits — not DesignRush blocking | Retry with exponential backoff (2s → 4s → 8s). |
Diagnostic checklist before opening an issue
- Baseline run.
category= a default slug,maxRecords: 5,maxPages: 3,scrapeProfiles: false,contactMode: "none",deliveryMode: "none". - Results returned? If yes, re-add profiles, filters and volume one step at a time.
- Short or empty? Raise
maxPages— filtering needs far more pages than the default 3. - Check the log for
Location filter :(did the site filter apply?) and for per-profile errors. - Confirm
contactModein the resolved input before reporting anything about outreach.
If the issue survives all five steps, open an Issues ticket on the Actor page (or email support) with the run ID, the exact input JSON, and what you expected.
❓ FAQ
Setup & access
Do I need a DesignRush account?
No. The Actor reads public directory and profile pages, and uses the site's public enquiry form. You need an Apify account and API token only.
Is this an official DesignRush API or tool?
No. This is an independent Actor and is not affiliated with, endorsed by, or sponsored by DesignRush.
Can I plug it into Claude, Cursor, or a LangChain agent?
Yes — it is a native MCP tool:
claude mcp add --transport http apify "https://mcp.apify.com?tools=techforce.global/design-rush--outreach-bot"
For agent-driven runs, pass contactMode: "none" unless a human has explicitly authorised outreach.
Outreach
Does this Actor really message agencies?
Only if you tell it to. With contactMode: "submit" and both contactName and contactEmail set, it fills and submits the agency's own enquiry form — a real message to a real business. payload mode extracts everything needed to send it later without sending anything; none skips it entirely.
Why would I use payload instead of submit?
Because it puts a human or a reviewed workflow between the scrape and the send. You get the POST URL, CSRF token, cookies and field values, and your own automation decides what actually goes out — which is also how you keep per-agency personalisation.
How long is a contactPayload valid?
Not long — _token and cookies are tied to the scraping session. Post promptly or re-run.
Should I use the default contactMessage?
No. Rewrite it. A generic template sent at volume is exactly what gets a sender domain blocked and a directory account restricted.
Data & filtering
Can I get agency email addresses?
No — DesignRush routes enquiries through its form rather than publishing addresses. For scraped agency emails use TopDevelopers Scraper instead.
Why did my filter return so few agencies?
maxRecords counts records after filtering, and the scraper only sees the pages it visits. Raise maxPages — the default of 3 is far too low for a name or location filter.
Why is everything "N/A" instead of empty?
"N/A" is this Actor's missing-value sentinel for every listing field. Compare against the string.
Can I add more categories?
Only by editing the Actor: add the slug → URL pair in my_actor/categories.py and the enum/enumTitles in input_schema.json.
Pricing
How is this billed?
Pay-per-event, from $2.00 per 1,000 results, less on higher Apify subscription tiers. Apify platform usage is billed separately — and because this Actor drives a real browser, scrapeProfiles: true is the biggest driver of that.
How do I make a run as cheap as possible?
scrapeProfiles: false with tight maxRecords and maxPages.
How do I guarantee an agent never overspends?
Pass maxTotalChargeUsd as a query parameter on the run endpoint — a hard per-execution ceiling.
🔗 Related Actors
Agency & B2B lead sources
| Actor | Best for | Why pick it over this one |
|---|---|---|
| TopDevelopers Scraper — IT Agency Leads | IT & software agencies from TopDevelopers.co with scraped email addresses, client reviews and review-derived insights | You need an actual email address per agency, or insight aggregates (avg rating, project types, budgets) |
| Google Maps Business Leads & Sales Intelligence | Any business type via Google Maps, with a website grade and pitch playbook per lead | You want agencies (or anything else) found by location rather than a curated directory |
| Google Maps Scraper | Plain Google Maps listings at the lowest cost per result | You only need name/address/phone/website/rating |
Enrichment & downstream pipeline
| Actor | Use it for |
|---|---|
| Advanced Website Crawling Actor | Crawl an agency's own site from website for clean HTML/Markdown/text context and contact pages |
| GOV.UK Business Scraper | Match UK agency names against Companies House records, with PSC / beneficial-ownership enrichment |
Suggested pipeline patterns
🎯 Vendor shortlist
Category run with scrapeProfiles: true and contactMode: "none" → rank on rating, hourlyRate and review depth → deliveryMode: "perAgency" into Airtable → brief the buying team.
✍️ Reviewed outreach
contactMode: "payload" → store contactPayload per agency → a human writes a specific message per shortlisted agency → your workflow posts the payload. Personalised, auditable, and never automated end-to-end.
🔎 Contact-route enrichment
This Actor for the directory profile → Advanced Website Crawling Actor on website to find a direct contact route → skip the directory form entirely.
🏛️ UK agency verification
This Actor for the shortlist → GOV.UK Business Scraper on name → attach company number, incorporation date and PSC data before signing anything.
Browse all Actors by Techforce Global at apify.com/techforce.global.
🔐 Compliance & Data Privacy
This is an independent Actor. It is not affiliated with, endorsed by, or sponsored by DesignRush. "DesignRush" is a trademark of its respective owner.
This Actor collects publicly available directory listings and profile content, and does not log into any account. But it differs from a pure scraper in one important way, so read this before using submit mode.
Submitting enquiry forms is a regulated action, not scraping.
- It sends a real message to a real business. Automating that at volume is the definition of unsolicited bulk contact, and the applicable rules — GDPR Art. 6/21, ePrivacy/PECR, CAN-SPAM, CASL — apply to form submissions the same way they apply to email. Establish your lawful basis before you run it, keep a record of it, and honour opt-outs.
- Automated form submission may breach the site's Terms of Service even when the data collection does not. Check DesignRush's terms, and don't route around any technical measure that says no.
- Send messages a human would defend. Rewrite the default
contactMessage, personalise per agency, keep volumes modest, and raiseprofileDelayrather than hammering the site.payloadmode exists precisely so a person can stay in the loop. - Misrepresentation is out of bounds. The contact details you submit must be your own and accurate — this Actor is not for posing as someone else.
Personal data. Team-member names and reviewer names in the profile blocks are personal data about identifiable individuals; GDPR and CCPA can apply. Store only what you need, for as long as you need it, and think twice before republishing reviewer identities.
You are responsible for ensuring your use complies with DesignRush's Terms of Service and all applicable law.
🆘 Support & Custom Pipeline Engineering
Need more categories, scheduled refreshes, a reviewed-outreach workflow, or a full CRM / data-warehouse integration?
- Email: bhavin.shah@techforceglobal.com
- Custom Enterprise Integrations: Book a 15-Minute Technical Consultation
- Maintained by: Techforce Global — Specialists in High-Performance Web Scrapers and Agentic Workflows.
Made with ❤️ by Techforce Global Specialists in High-Performance B2B Lead Data Extraction and AI Automation.
🏷️ Structured data for search & AI discovery
{"@context": "https://schema.org","@type": "SoftwareApplication","name": "DesignRush Outreach Bot — Agency Leads, Reviews & Contact-Form Outreach","applicationCategory": "BusinessApplication","operatingSystem": "Cloud (Apify platform)","description": "Extracts agency listings from DesignRush.com across 10 categories — name, website, location, rating, hourly rate, team size, slogan and description — optionally opens each profile for reviews, services, team members and clients, and can export or submit the agency's contact-form payload, with optional delivery to Airtable, HubSpot, Notion, Slack, Google Sheets, or any authorized MCP connector.","url": "https://apify.com/techforce.global/design-rush--outreach-bot","offers": {"@type": "Offer","price": "2.00","priceCurrency": "USD","description": "From $2.00 per 1,000 results, pay-per-event"}}