How to Detect Contact Form 7 on Any Website (API Guide)
Short answer: Contact Form 7 stamps wpcf7 all over the rendered page — in form container classes, input classes, hidden fields, and a global JavaScript object — and loads its assets from /wp-content/plugins/contact-form-7/. You can spot it with curl -s https://example.com | grep -o wpcf7 | head -1, or get a structured JSON answer from the free /demo endpoint with no API key. The rest of this guide covers every fingerprint and how to scale detection across a whole list of sites.
Contact Form 7 is one of the oldest and most widely installed WordPress plugins in existence — it has shipped with a huge share of WordPress builds since 2007 and still sits on millions of active installs. That ubiquity makes it a useful detection target: finding Contact Form 7 on a site confirms the site runs WordPress, tells you the owner relies on a free, developer-configured form rather than a paid form SaaS, and gives agencies and lead-gen teams a concrete conversation starter.
What Is Contact Form 7 and Why Detect It
Contact Form 7 (often abbreviated CF7, and prefixed wpcf7 in code) is a free WordPress plugin that manages multiple contact forms with Ajax-powered submission, CAPTCHA support, and Akismet spam filtering. It is deliberately minimal: no drag-and-drop builder, no hosted dashboard, just shortcodes and markup. That minimalism is exactly why it shows up everywhere from hobby blogs to large corporate sites.
Reasons teams detect it:
- WordPress confirmation. Contact Form 7 only runs on WordPress, so a positive detection doubles as a CMS detection.
- Lead qualification for form and marketing tools. A site on Contact Form 7 has a working form but none of the analytics, routing, or CRM sync that paid form products offer. Vendors selling form builders, chat widgets, or marketing automation treat CF7 sites as a natural prospect segment.
- Agency plugin audits. Before quoting a WordPress maintenance or migration job, agencies inventory the plugins in play. CF7 is one of the most common finds, often alongside page builders like Elementor.
- Security triage. Popular plugins are popular attack surface. Knowing which of your monitored domains run CF7 — and which version — is the first step in checking exposure when a plugin advisory lands.
Manual Ways to Detect Contact Form 7
Contact Form 7 renders directly into the page HTML and loads its own script and stylesheet, so it leaves three distinct fingerprints you can check by hand.
Check the Page Source for wpcf7 Markers
Every form the plugin renders is wrapped in a container whose class and ID both carry the wpcf7 prefix, and the inputs inside it use wpcf7-form-control classes:
<div class="wpcf7" id="wpcf7-f123-p45-o1">
<form action="/contact/#wpcf7-f123-p45-o1" method="post" class="wpcf7-form init">
<input type="text" name="your-name"
class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required">
...
</form>
</div>
On the page that hosts the form, a one-liner is enough:
$ curl -s https://example.com/contact/ | grep -o "wpcf7" | head -1
wpcf7
One caveat: this marker only appears on pages that actually render a form. The homepage of a CF7 site may show nothing while /contact/ lights up, so a homepage-only grep can produce false negatives.
Look for the contact-form-7 Plugin Path in Assets
WordPress serves plugin assets from a predictable path, and Contact Form 7 is no exception. Any page that enqueues the plugin's script or stylesheet references it directly:
<link rel="stylesheet"
href="https://example.com/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.9.8">
<script src="https://example.com/wp-content/plugins/contact-form-7/includes/js/index.js?ver=5.9.8"></script>
Two things make this the strongest manual signal. First, the /wp-content/plugins/contact-form-7/ path is unambiguous — no other software serves files from it. Second, WordPress appends the plugin version as a cache-busting ?ver= parameter, so the version number (here 5.9.8) rides along for free. This script URL is precisely the fingerprint DetectZeStack matches, and the ?ver= value is what populates the version field in the API response.
$ curl -s https://example.com | grep -o "plugins/contact-form-7[^\"']*"
plugins/contact-form-7/includes/css/styles.css?ver=5.9.8
plugins/contact-form-7/includes/js/index.js?ver=5.9.8
Inspect Network Requests for the wp-json/contact-form-7 REST Route
Since version 5.4, Contact Form 7 submits forms over the WordPress REST API. Open DevTools, go to the Network tab, submit the form, and you will see a POST to a route like:
POST /wp-json/contact-form-7/v1/contact-forms/123/feedback
The route namespace contact-form-7/v1 is another dead giveaway. You can also probe it without submitting anything — the plugin registers the namespace in the site's REST index:
$ curl -s https://example.com/wp-json/ | grep -o "contact-form-7/v1" | head -1
contact-form-7/v1
This works even on sites where no page currently renders a form, though some hardened WordPress installs disable or restrict /wp-json/ entirely.
Why Manual Detection Breaks at Scale
All three manual checks work for one site. They stop working the moment you have a list:
- The markers live on different pages. The
wpcf7container is on the contact page, the script tag is wherever the form loads, and the REST index is at/wp-json/. A reliable manual check means fetching several URLs per site. - Grep gives you a string, not data. You still have to parse the version out of the
?ver=parameter, handle redirects, deal with sites that block plaincurluser agents, and normalize the output into something a spreadsheet or CRM can ingest. - You learn nothing else. A grep for
wpcf7tells you nothing about the site's theme, page builder, analytics, hosting, or the rest of the stack — which is usually the context that makes the detection useful.
An API call solves all three at once: one request per site, structured JSON out, and the full technology stack in the same response.
Detect Contact Form 7 with the DetectZeStack API
The DetectZeStack API runs its full fingerprint database against a URL — HTML source, script URLs, DOM structure, JavaScript globals, headers, and DNS — and returns everything it finds as structured JSON. Contact Form 7 is fingerprinted by its script path (with version capture), its wpcf7 JavaScript global, and the plugin stylesheet link in the DOM.
Try It Free with the Demo Endpoint
The public /demo endpoint runs the same detector pipeline with no authentication. It is IP rate-limited, but perfect for a quick check or for confirming the response shape before you integrate:
curl -s "https://detectzestack.com/demo?url=https://example.com" | python3 -m json.tool
Full Detection with /analyze
For production use, sign up on RapidAPI and call /analyze with your key. When Contact Form 7 is present, the response looks like this:
curl -s "https://detectzestack.p.rapidapi.com/analyze?url=https://example.com" \
-H "X-RapidAPI-Key: YOUR_KEY" \
-H "X-RapidAPI-Host: detectzestack.p.rapidapi.com"
{
"url": "https://example.com",
"domain": "example.com",
"technologies": [
{
"name": "Contact Form 7",
"categories": ["WordPress plugins", "Form builders"],
"confidence": 100,
"description": "Contact Form 7 is an WordPress plugin which can manage multiple contact forms. The form supports Ajax-powered submitting, CAPTCHA, Akismet spam filtering.",
"website": "https://contactform7.com",
"icon": "Contact Form 7.png",
"source": "http",
"version": "5.9.8",
"cpe": ""
},
{
"name": "WordPress",
"categories": ["CMS", "Blogs"],
"confidence": 100,
"description": "WordPress is a content management system.",
"website": "https://wordpress.org",
"icon": "WordPress.svg",
"source": "http",
"version": "",
"cpe": ""
}
],
"categories": {
"WordPress plugins": ["Contact Form 7"],
"Form builders": ["Contact Form 7"],
"CMS": ["WordPress"]
},
"meta": { "status_code": 200, "tech_count": 14, "scan_depth": "full" },
"cached": false,
"response_ms": 1842
}
A few things worth noticing. Contact Form 7 is classified under two categories — WordPress plugins and Form builders — so it appears twice in the top-level categories map, which lets you filter by either angle. The version field is parsed from the ?ver= parameter on the plugin's script URL when present. And WordPress itself shows up in the same response, because the same page that betrays the plugin fires WordPress's own fingerprints too.
To narrow the output to just the Contact Form 7 entry, pipe through jq:
curl -s "https://detectzestack.p.rapidapi.com/analyze?url=https://example.com" \
-H "X-RapidAPI-Key: YOUR_KEY" \
-H "X-RapidAPI-Host: detectzestack.p.rapidapi.com" \
| jq '.technologies[] | select(.name == "Contact Form 7")'
Yes/No Checks with /check for a Single Technology
If all you want is a boolean, the /check endpoint answers the narrower question “does this site run this specific technology?” directly. The tech parameter is case-insensitive:
curl -s "https://detectzestack.p.rapidapi.com/check?url=https://example.com&tech=Contact%20Form%207" \
-H "X-RapidAPI-Key: YOUR_KEY" \
-H "X-RapidAPI-Host: detectzestack.p.rapidapi.com"
{
"domain": "example.com",
"technology": "Contact Form 7",
"detected": true,
"confidence": 100,
"version": "5.9.8",
"categories": ["WordPress plugins", "Form builders"],
"response_ms": 1421,
"cached": false
}
When the technology is not found, detected comes back false with a confidence of 0. This shape is convenient for pipelines that just need to branch on a boolean — no array filtering required.
Detecting Contact Form 7 Across Many Sites with /analyze/batch
Checking one site is useful; checking a list is where this earns its keep. The POST /analyze/batch endpoint accepts up to 10 URLs per request and scans them concurrently:
curl -X POST "https://detectzestack.p.rapidapi.com/analyze/batch" \
-H "X-RapidAPI-Key: YOUR_KEY" \
-H "X-RapidAPI-Host: detectzestack.p.rapidapi.com" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"example.com",
"wordpress.org",
"contactform7.com",
"example.org"
]
}'
To turn a domain list into a clean list of Contact Form 7 sites, loop in batches of 10 and filter each result:
import requests
API_URL = "https://detectzestack.p.rapidapi.com/analyze/batch"
HEADERS = {
"X-RapidAPI-Key": "YOUR_KEY",
"X-RapidAPI-Host": "detectzestack.p.rapidapi.com",
"Content-Type": "application/json",
}
def chunk(items, size=10):
for i in range(0, len(items), size):
yield items[i:i + size]
domains = ["example.com", "wordpress.org", "contactform7.com"]
cf7_sites = []
for batch in chunk(domains):
resp = requests.post(API_URL, json={"urls": batch}, headers=HEADERS)
for item in resp.json().get("results", []):
result = item.get("result") # None if that URL errored
if not result:
continue
for tech in result.get("technologies", []):
if tech["name"] == "Contact Form 7":
cf7_sites.append((result["domain"], tech.get("version", "")))
print("Sites using Contact Form 7:", cf7_sites)
Each URL in a batch counts as one request against your monthly quota, so a 10-URL batch consumes 10 requests. For the full pattern — rate-limit handling, retries, and CSV output — see How to Batch-Scan 1,000 Websites.
What Contact Form 7 Tells You About a Website's Stack
It Confirms WordPress and Hints at Plugin-Heavy Builds
Because Contact Form 7 cannot run outside WordPress, a positive detection is also a CMS detection — and its /wp-content/plugins/ asset path is itself a WordPress signature. If your real question is “what CMS is this?”, start with how to detect what CMS a website uses instead; if you already know it is WordPress, the CF7 signal refines the picture:
| Signal Combination | What It Suggests |
|---|---|
| Contact Form 7 alone | A lean, developer-configured build — the site owner favors free, minimal tooling over form SaaS |
| Contact Form 7 + Elementor | A classic agency-built small-business site; likely more plugins under the hood |
| Contact Form 7 + Yoast SEO | An owner investing in organic search but not yet in marketing automation |
| Contact Form 7 + managed WP hosting | Budget for infrastructure exists; form tooling is a plausible upsell conversation |
All of these combinations come back in a single /analyze response, since the same scan surfaces page builders, SEO plugins like Yoast, analytics tools, and hosting signals like WP Engine alongside the form plugin. For sales teams, that means one API call per domain produces the whole qualification picture, not just a yes/no on the form.
One honest caveat: version detection depends on the ?ver= parameter surviving to the rendered page. Some caching and optimization plugins strip or rewrite query strings on static assets, in which case Contact Form 7 is still detected via its other fingerprints but the version field comes back empty.
Get Your API Key
Everything above runs on the free tier: 100 requests per month, no credit card. Sign up on RapidAPI, grab your key, and the /analyze, /check, and /analyze/batch examples in this guide work as-is with your key substituted in.
Conclusion
Contact Form 7 is one of the easiest technologies on the web to detect: it stamps wpcf7 into its markup, serves assets from an unambiguous /wp-content/plugins/contact-form-7/ path with the version in the URL, and registers a contact-form-7/v1 REST route. Manual checks with curl and DevTools work fine for a single site. For anything more — a prospect list, a plugin audit across client sites, a security inventory — the DetectZeStack API turns the same fingerprints into structured JSON, adds the rest of the tech stack in the same response, and scales to thousands of domains through batching.
Related Reading
- Check If a Website Uses WordPress — The CMS Contact Form 7 confirms, detected via headers, meta tags, and file paths
- Find Companies Using Elementor — Pair the CF7 signal with the page builder to profile agency-built WordPress sites
- How to Detect Yoast SEO on Any Website — Another WordPress plugin with unmistakable HTML fingerprints
- How to Detect What CMS a Website Uses — WordPress, Shopify, Squarespace, and 30+ CMS platforms
- Find Companies Using WP Engine — Add managed-hosting signals to your WordPress prospect segment
- How to Batch-Scan 1,000 Websites — Scale the /analyze/batch pattern end to end
- Website Technology Checker API — Full API reference and integration guide
Try DetectZeStack Free
100 requests per month, no credit card required. WordPress, plugin, CMS, analytics, and infrastructure detection on every plan.
Get Your Free API Key