SaaS Battlecard Generator avatar

SaaS Battlecard Generator

Pricing

from $28.00 / 1,000 battlecard generateds

Go to Apify Store
SaaS Battlecard Generator

SaaS Battlecard Generator

Generate sales battlecards from competitors' public pricing and feature pages: plan tiers and prices, a feature matrix, strengths and weaknesses, objection handling and win/loss tips, with a source URL for every fact. JSON, markdown and a one-pager per competitor.

Pricing

from $28.00 / 1,000 battlecard generateds

Rating

0.0

(0)

Developer

AIDevs

AIDevs

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

11 days ago

Last modified

Features

Limited permissions

Share

Sales battlecards built from your competitors' public pricing and feature pages, for account executives, sales engineers, product marketers and founders. Every fact cites its source URL; nothing is invented.

Sample battlecard

Fictional products on example.com / example.org, rendered by the Actor's own one-pager template (excerpt):

BATTLECARD — ExampleTasks vs DemoBoards
Mode: head_to_head | Status: ok | Confidence: 86/100
PRICING AT A GLANCE
ExampleTasks: USD 8.0/monthly | free tier ✓ | contact-sales ✓
DemoBoards: USD 12.0/monthly | no free tier | contact-sales ✓
CAPABILITIES SIGNAL (top promoted, by company)
ExampleTasks: Kanban boards, Sprint planning, Time tracking, Roadmaps
DemoBoards: Kanban boards, Whiteboards, Automations, Guest access
WHY WE WIN / WHY WE LOSE
DemoBoards:
+ Promotes capabilities we don't surface: automations, guest access, whiteboards.
- No free tier — friction to evaluate.
- Higher entry tier than ours: USD 12.0 vs USD 8.0.
TOP OBJECTIONS
Objection: "DemoBoards promotes Kanban boards."
Response : Validate whether Kanban boards is in their core product or a marketing headline. ...
SOURCES
(DemoBoards, pricing) https://boards.example.org/pricing
(DemoBoards, features) https://boards.example.org/features

Each battlecard also comes as structured JSON (pricing tiers, feature matrix, strengths and weaknesses, objection handling, win/loss guidance, risk flags, sources) and as Markdown for your wiki or team chat.

Need a deeper read of one competitor's website (positioning, messaging, audience)? Pair this Actor with the Competitor Website Analyzer.

Quick start

  1. Enter your product in Our company and one rival in Competitors, or switch Mode to Market scan and list up to 10 competitors.
  2. Add each company's site under Our company website and Competitor websites. The Actor then reads only those sites; with just a name it tries likely domains. Some SaaS vendors forbid automated access to their websites in their terms; check before you add a site.
  3. Click Start. After 30–90 seconds the Output tab shows one battlecard per competitor, the full result (OUTPUT) and a run summary (RUN_SUMMARY).

The prefilled input is a demo pair: Apify (the platform this Actor runs on) as your company and Linear as the competitor. They were picked because both sites allow automated access to the public pages the Actor reads, not as a real match-up.

Cost

You pay per delivered battlecard (shown in the Store as "Battlecard generated"):

Apify planPer battlecard100 battlecards1,000 battlecards
Free$0.04$4.00$40.00
Bronze$0.036$3.60$36.00
Silver$0.032$3.20$32.00
Gold and above$0.028$2.80$28.00

Platform usage is included in the price. Each run also has an automatic start fee of $0.00005 per GB of run memory.

  • A head-to-head run delivers at most 1 battlecard; a market scan of N competitors delivers at most N.
  • Not billed: a competitor whose website could not be confirmed (candidates_only), a website with no extractable pricing or features (no_data), the same website listed twice (duplicate), invalid input and failed runs. You still see them in OUTPUT and RUN_SUMMARY; they never reach the dataset.
  • Your maximum charge per run is respected. If the next battlecard would exceed it, the Actor stops delivering and lists the rest in RUN_SUMMARY as charge_limit_reached. If not even one battlecard fits, nothing is fetched.

FAQ

Is it legal? It depends on the sites you add and on what you do with the results; this isn't legal advice. The Actor reads only public marketing pages (homepage, pricing, features) of the companies you name. It never logs in, follows each site's robots.txt, and stops at CAPTCHAs, login walls, rate limits and block pages instead of getting around them; it says so in the status message and in RUN_SUMMARY.blocked_sites. Each vendor's own terms of use apply to its website, and some SaaS vendors forbid automated access to their websites in their terms; check before you add a site. The pages are about products, not people, but if one contains personal data (a name on a page, say), you are the data controller and need a lawful basis under the GDPR or similar laws to keep or use it. Vendor names are used only to identify the products compared.

How does the Actor identify itself? Requests identify as AIDevsBot; site owners can opt out with User-agent: AIDevsBot / Disallow: / in robots.txt. If you set a Custom User-Agent, use an honest one that identifies you. The AIDevsBot rules still apply, and so do any rules for the bot named in your User-Agent.

How does it handle robots.txt? Before the first page of a site it reads that site's robots.txt and follows the group for AIDevsBot. If there is none it uses the group for SaaSCompetitorBattlecardsBot (the Actor's earlier User-Agent), otherwise the one for all bots (User-agent: *). The most specific rule wins. If robots.txt answers 401 or 403, the whole site counts as disallowed; other 4xx answers (404 and so on) mean there are no rules. A 429, a server error, a timeout or no answer at all skips the site for the rest of the run. A disallowed page is never requested, not even through a redirect. The battlecard says which pages were skipped (a note and a robots_disallowed risk flag), the status message and RUN_SUMMARY.robots_disallowed name the site, and nothing is billed for the missing data.

What does tdmReserved mean? Under EU copyright law (DSM Directive, Art. 4(3)) a site can reserve its text-and-data-mining rights in a machine-readable way: the TDMRep tdm-reservation HTTP header or <meta> tag (the tag wins). Every page record (companies[].pages[] and sources[]) has tdmReserved (true or false) and tdmPolicy (the policy URL the site names, else null), and the battlecard gets a tdm_reserved risk flag. The Actor still extracts the public prices and features; check the site's policy before you reuse its content, for example in an AI system. /.well-known/tdmrep.json is not read, so false only means the page itself carries no reservation.

Why does my run say candidates_only? The Actor couldn't confirm an official website above your confidence_threshold. Look at companies[*].candidates in OUTPUT, pick the right URL, and re-run with it in competitor_websites. Nothing was charged.

Why was a competitor not billed? RUN_SUMMARY.not_delivered lists every competitor without a battlecard and the reason: candidates_only, no_data, duplicate or charge_limit_reached.

Wrong charge? Report it in the Issues tab; we reply within 14 days.

What happens to my data? AIDevs processes your input and results only to run the Actor. Nothing is kept or shared beyond your own Apify storages.

Is the output current? Pages are fetched at run time, with no cache between runs. Each run is a snapshot; schedule it if you want to track changes.

Can I trust the strengths and weaknesses? Treat them as a first draft. They are derived by fixed rules from the extracted facts (free tier, entry price, promoted features). They don't capture product quality, support or roadmap.

Does it use AI? No. Discovery and extraction are rule-based and deterministic: the same pages give the same battlecard.

Works with AI agents through Apify's MCP server.

Limitations

  • JavaScript-only pricing pages come back with empty plans and a no_pricing_page risk flag; the Actor reads server-rendered HTML only.
  • Sub-products of large brands (a product page under a bigger domain) need an explicit competitor_websites URL.
  • Name-only companies: without a website the Actor tries <name>.com, www.<name>.com, <name>.io and so on, and stops at the first that matches the brand. A guess can still land on the wrong site, so give the website when you know it.
  • Marketing prose vs. feature labels: taglines and slogans are filtered out, so a few genuine features may be dropped too.
  • Snapshots only: no built-in history or change tracking.
  • Sites that block automated access are skipped, not worked around; their battlecards come back empty and are not billed. Requests identify as AIDevsBot, never as a browser, so a site that only lets browsers in may block the run.
  • robots.txt that can't be read (server error, timeout) skips that site for the run, even if it would have allowed the Actor.
  • TDM signals: tdmReserved covers the TDMRep header and <meta> tag of each page, not /.well-known/tdmrep.json or reservations written only in a site's terms.
  • At most 10 competitors per run.

More tools from AIDevs


Example comparisons

Published example runs (real public pages, so results change over time; check each vendor's terms before you run your own):

  • Slack vs Microsoft Teams battlecard
  • SaaS competitor analysis market scan
  • Competitor pricing comparison
  • Sales objection handling battlecard
  • Figma vs Sketch vs Adobe XD comparison

Not affiliated with, endorsed by or sponsored by Linear, Slack, Microsoft, Figma, Sketch or Adobe.

Input

FieldTypeDefaultDescription
modeenumhead_to_headhead_to_head (your product vs one competitor) or market_scan (several competitors).
our_companystringApifyYour company name. Required for head_to_head.
our_websitestringhttps://apify.comYour website. When given, it is the only site tried for your company.
competitorsarray of strings["Linear"]1–10 competitor names. head_to_head uses only the first.
competitor_websitesobject{"Linear": "https://linear.app"}{name: url} map. A competitor with a URL here is looked up on that site only (recommended).
confidence_thresholdint60Below this website confidence (0–100) the Actor returns ranked candidates instead of guessing.
max_pages_per_companyint6Cap on page requests per company (robots.txt not counted).
currency_hintstringUSDHint when a page shows several currencies.
locale_hintstringen-USHint for localized pricing pages.
user_agentstringAIDevsBot defaultOptional override. Use an honest User-Agent that identifies you; don't impersonate a browser.
request_timeout_secondsint20Per-request HTTP timeout.

Head-to-head example (the demo pair):

{
"mode": "head_to_head",
"our_company": "Apify",
"our_website": "https://apify.com",
"competitors": ["Linear"],
"competitor_websites": { "Linear": "https://linear.app" }
}

Output

Dataset (billed): one record per delivered battlecard. The Overview view shows competitor, website, pricing headline, status, confidence and the one-pager; Battlecard detail shows the structured sections.

Key-value store (never billed): OUTPUT holds the full result of every run, including failed and candidates_only runs; RUN_SUMMARY lists what was delivered and what was not, with reasons, plus any sites that blocked automated access (blocked_sites) and pages robots.txt kept the Actor from (robots_disallowed).

FieldDescription
primary_competitorThe competitor this battlecard is about.
competitor_websiteIts resolved website.
pricing_headlineOne line, e.g. 3 plans · from USD 12/monthly · free tier.
request_contextEcho of the request: mode, companies, threshold, timestamps.
companiesPer-company resolution: website, confidence, candidates, pages found. Each page has tdmReserved / tdmPolicy.
confidencePer-company website/pricing/feature scores, composite and overall.
sourcesEvery URL used, with category (homepage / pricing / features) and tdmReserved / tdmPolicy.
pricing_summaryPlans, prices, billing periods, free/custom flags, lowest paid price.
feature_comparisonFeature × company matrix (yes / unknown).
positioning_summaryShort positioning per company, labelled as inferred.
strengths_and_weaknessesPer competitor, with citations.
objection_handlingLikely objections and suggested responses.
win_loss_guidanceWhen to lean in, when to walk away.
risk_flagsData-quality and access warnings (low confidence, no pricing page, no data, duplicate, site_blocked, robots_disallowed, tdm_reserved, …).
battlecard_markdown, one_pager_textReadable renderings derived from the JSON.
output_statusok / partial / candidates_only / failed, plus per_company codes: ok, partial, no_data, duplicate, candidates_only.
disclaimerResearch-material disclaimer carried by every record.
chargeable_event_count, paid_event_nameBilling transparency (1 per record).

Trust contract

  • Will cite the source URL for every extracted fact and label inferred insights as inferred.
  • Will return ranked candidates instead of a guessed website when confidence is low.
  • Will keep enterprise / contact-sales plans as is_custom: true without inventing a price.
  • Will read only the website you give for a company, and request each page at most once per run.
  • Will not spoof a browser User-Agent or bypass robots.txt.

How it works

  1. Discovery. Uses the website you give (and only that site), or, with just a name, tries likely domains in order and stops at the first whose <title>, og:site_name and meta description match the brand.
  2. Page discovery. Finds pricing and features pages from homepage links and common paths (/pricing, /features, …), within max_pages_per_company requests. robots.txt is checked before every request.
  3. Extraction. Rule-based parsing of plan cards (name, price, billing period, free/custom) and of feature headings and bullets, with tagline and footer filters. It reuses the pages fetched in step 2.
  4. Assembly. Builds the JSON first, then derives the Markdown and one-pager from it.

For developers

.actor/
actor.json, input_schema.json, dataset_schema.json, output_schema.json
store-listing.json # Store copy, synced by hand at deploy (not used at runtime)
main.py # Entry point: input, budget check, push, OUTPUT, RUN_SUMMARY
src/
billing.py # Pay-per-event helpers (Apify SDK 4.x charging manager)
models.py # Pydantic input and output models
utils.py # HTTP (User-Agent, redirects, blocks, TDMRep), URL and price helpers
robots.py # robots.txt rules (RFC 9309), one fetch per site per run
discovery.py # Website + pricing/features page discovery
extract_pricing.py # Plan-card extraction
extract_features.py # Feature-label extraction
battlecard.py # Assembly, per-company status, Markdown, one-pager
tests/ # Offline unit tests (no network)
examples/ # More sample inputs (real vendor names: check their terms first)

Confidence: composite = 0.45 × website + 0.35 × pricing + 0.20 × features; the run's overall confidence is the mean across companies.

Run locally (fetches live pages):

pip install -r requirements.lock.txt
cp sample_input.json INPUT.json # the SDK reads ./INPUT.json when no stored input exists
python main.py # results land in ./storage/

Tests (offline, a few seconds):

pip install -r requirements-dev.txt
pytest

See CHANGELOG.md for the version history.

Terms

Your use of this Actor is governed by Apify's Standard Actor Contract, the default terms for Actors in Apify Store. Battlecards are research material built from public marketing pages: check each fact against its source URL before you use it with customers.