How to Detect if a Website Uses WordPress (Programmatically via API)
WordPress powers over 40% of the web. Whether you are building a competitive analysis tool, qualifying leads, auditing websites for security vulnerabilities, or just curious about a site's tech stack, knowing how to detect WordPress programmatically is a valuable capability.
In this guide, we will cover two approaches: the manual method (inspecting HTTP responses yourself) and the API method (using StackPeek to detect WordPress and its plugins/themes with a single API call). We will include working code examples in curl, Node.js, and Python.
The Quick Way: Detect WordPress with One API Call
If you want to skip the manual inspection and get a structured answer immediately, use the StackPeek API:
curl "https://stackpeek.web.app/api/v1/detect?url=https://techcrunch.com"
Response:
{
"url": "https://techcrunch.com",
"technologies": [
{ "name": "WordPress", "category": "cms", "confidence": 0.99 },
{ "name": "PHP", "category": "language", "confidence": 0.95 },
{ "name": "Cloudflare", "category": "cdn", "confidence": 0.98 },
{ "name": "Google Analytics", "category": "analytics", "confidence": 0.97 },
{ "name": "Google Tag Manager", "category": "analytics", "confidence": 0.96 }
],
"scanTime": 412
}
WordPress detected with 99% confidence, plus the full tech stack, all in 412ms. No API key required for the free tier (100 scans/day).
But if you want to understand what is happening under the hood — or you want to build your own detection logic — read on.
How WordPress Detection Works: The Signals
Every WordPress site leaves fingerprints in its HTML source, HTTP headers, and file structure. Here are the key signals that detection tools (including StackPeek) look for:
1. The /wp-content/ directory
This is the most reliable WordPress indicator. WordPress stores themes, plugins, and uploads in /wp-content/. Almost every WordPress site loads CSS, JavaScript, or images from paths like:
/wp-content/themes/flavor-developer/style.css
/wp-content/plugins/jetpack/css/jetpack.css
/wp-content/uploads/2026/03/hero-image.jpg
Even heavily customized WordPress sites rarely rename this directory. If you find wp-content anywhere in the page source, it is WordPress with near-100% certainty.
2. The /wp-includes/ directory
WordPress core JavaScript and CSS files are served from /wp-includes/:
/wp-includes/js/jquery/jquery.min.js
/wp-includes/css/dist/block-library/style.min.css
This directory is part of WordPress core and is almost never renamed or removed.
3. Meta generator tag
By default, WordPress adds a meta tag in the HTML <head>:
<meta name="generator" content="WordPress 6.5.2" />
This is the easiest signal to check, but many security-conscious sites remove it. About 60-70% of WordPress sites still have it. When present, it also reveals the exact WordPress version.
4. The /wp-json/ REST API endpoint
WordPress ships with a built-in REST API. You can check if it exists by requesting:
curl -s -o /dev/null -w "%{http_code}" "https://example.com/wp-json/"
A 200 response confirms WordPress. The endpoint returns a JSON object describing the site's REST API routes. Some sites disable this, but most leave it enabled.
5. The /xmlrpc.php endpoint
WordPress includes xmlrpc.php for remote publishing. Requesting it will typically return a 200 status with an XML response containing "XML-RPC server accepts POST requests only." This is another strong WordPress indicator, though some sites disable it for security.
6. WordPress-specific cookies
WordPress sets cookies with names like wordpress_test_cookie, wp-settings-*, and wordpress_logged_in_*. These appear in the Set-Cookie response header.
7. The X-Powered-By header
Some WordPress hosting providers set X-Powered-By: WP Engine or similar headers that indirectly confirm WordPress.
Detection Signal Reliability
| Signal | Reliability | Notes |
|---|---|---|
/wp-content/ in HTML |
Very high | Present on ~95% of WordPress sites |
/wp-includes/ in HTML |
Very high | Core WordPress directory |
| Meta generator tag | Medium | Removed by ~30-40% of sites |
/wp-json/ endpoint |
High | Active on most installs |
/xmlrpc.php |
Medium | Often disabled for security |
| WordPress cookies | Low | Only visible to logged-in users |
Manual Detection: Code Examples
Here is how to build a basic WordPress detector yourself. These examples check the most reliable signals.
Bash / curl
#!/bin/bash
URL="https://techcrunch.com"
# Fetch the HTML and check for WordPress signals
HTML=$(curl -sL "$URL")
if echo "$HTML" | grep -qi "wp-content\|wp-includes"; then
echo "WordPress detected (wp-content/wp-includes found)"
elif echo "$HTML" | grep -qi 'meta name="generator" content="WordPress'; then
echo "WordPress detected (meta generator tag)"
else
# Check wp-json endpoint as fallback
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${URL}/wp-json/")
if [ "$STATUS" = "200" ]; then
echo "WordPress detected (wp-json endpoint active)"
else
echo "WordPress not detected"
fi
fi
Node.js
async function detectWordPress(url) {
const resp = await fetch(url);
const html = await resp.text();
const signals = {
wpContent: /wp-content\//i.test(html),
wpIncludes: /wp-includes\//i.test(html),
metaGenerator: /meta[^>]+generator[^>]+WordPress/i.test(html),
};
const isWordPress = Object.values(signals).some(Boolean);
if (!isWordPress) {
// Fallback: check wp-json endpoint
try {
const apiResp = await fetch(`${url}/wp-json/`);
signals.wpJson = apiResp.ok;
} catch (e) {
signals.wpJson = false;
}
}
return {
isWordPress: Object.values(signals).some(Boolean),
signals,
};
}
// Usage
detectWordPress("https://techcrunch.com")
.then(result => console.log(result));
// Output:
// { isWordPress: true, signals: { wpContent: true, wpIncludes: true, metaGenerator: false } }
Python
import re
import requests
def detect_wordpress(url):
resp = requests.get(url, timeout=10)
html = resp.text
signals = {
"wp_content": bool(re.search(r"wp-content/", html, re.I)),
"wp_includes": bool(re.search(r"wp-includes/", html, re.I)),
"meta_generator": bool(re.search(
r'meta[^>]+generator[^>]+WordPress', html, re.I
)),
}
is_wordpress = any(signals.values())
if not is_wordpress:
# Fallback: check wp-json endpoint
try:
api_resp = requests.get(f"{url}/wp-json/", timeout=5)
signals["wp_json"] = api_resp.status_code == 200
except:
signals["wp_json"] = False
return {
"is_wordpress": any(signals.values()),
"signals": signals,
}
result = detect_wordpress("https://techcrunch.com")
print(result)
# {'is_wordpress': True, 'signals': {'wp_content': True, 'wp_includes': True, 'meta_generator': False}}
The Problem with Manual Detection
The manual approach works, but it has real limitations:
- Multiple HTTP requests: You may need to fetch the HTML, then probe
/wp-json/, then/xmlrpc.php. Each adds latency and can trigger rate limiting. - Edge cases: Headless WordPress (using WP as a backend API with a React or Next.js frontend) will not show
wp-contentin the HTML. Thewp-jsonendpoint check catches these, but not always. - False positives: Some non-WordPress sites reference
wp-contentin links or iframes to WordPress-hosted content. - Maintenance burden: WordPress changes its fingerprints across versions. Your detection logic needs ongoing updates.
- No plugin or theme detection: Knowing a site uses WordPress is step one. Knowing it uses WooCommerce, Yoast SEO, or Elementor is where the real value is — and that requires a much larger fingerprint database.
This is exactly why using an API like StackPeek makes sense. It handles all the edge cases, maintains the fingerprint database, and returns structured results with confidence scores.
Better Approach: Use the StackPeek API
Instead of writing and maintaining your own detection code, let StackPeek handle it. Here is how to check for WordPress and filter the results programmatically.
Node.js: Check if a site uses WordPress
async function isWordPress(url) {
const resp = await fetch(
`https://stackpeek.web.app/api/v1/detect?url=${encodeURIComponent(url)}`
);
const data = await resp.json();
const wp = data.technologies.find(
t => t.name.toLowerCase() === "wordpress"
);
return {
isWordPress: !!wp,
confidence: wp ? wp.confidence : 0,
fullStack: data.technologies,
};
}
// Check a single site
const result = await isWordPress("https://techcrunch.com");
console.log(result.isWordPress); // true
console.log(result.confidence); // 0.99
Python: Batch-check a list of domains
import requests
def check_wordpress_batch(domains):
results = []
for domain in domains:
resp = requests.get(
f"https://stackpeek.web.app/api/v1/detect?url=https://{domain}"
)
data = resp.json()
techs = {t["name"].lower(): t for t in data["technologies"]}
results.append({
"domain": domain,
"is_wordpress": "wordpress" in techs,
"confidence": techs.get("wordpress", {}).get("confidence", 0),
"all_techs": [t["name"] for t in data["technologies"]],
})
return results
domains = ["techcrunch.com", "stripe.com", "whitehouse.gov", "bbc.com"]
results = check_wordpress_batch(domains)
for r in results:
status = "WordPress" if r["is_wordpress"] else "Not WordPress"
print(f"{r['domain']}: {status} ({', '.join(r['all_techs'])})")
# Output:
# techcrunch.com: WordPress (WordPress, PHP, Cloudflare, Google Analytics)
# stripe.com: Not WordPress (Next.js, React, Cloudflare, Segment)
# whitehouse.gov: WordPress (WordPress, PHP, Akamai, Google Analytics)
# bbc.com: Not WordPress (React, AWS, Chartbeat, Google Tag Manager)
With the StackPeek API, you get WordPress detection plus the entire tech stack in a single call. No need to write separate detection logic for each technology.
Beyond Detection: What Can You Learn About a WordPress Site?
Knowing a site uses WordPress is just the starting point. Here is what you can do with that information:
Identify WordPress plugins
Many WordPress plugins leave detectable traces — script tags, CSS files in /wp-content/plugins/, or specific HTML patterns. StackPeek identifies common plugins like WooCommerce, Yoast SEO, Elementor, Contact Form 7, and others. This is valuable for:
- Competitive research: See what plugins your competitors use for SEO, ecommerce, and marketing
- Security auditing: Identify plugins with known vulnerabilities
- Sales prospecting: Find sites using a competitor's plugin that you could replace
Detect the WordPress theme
The theme is usually identifiable from the /wp-content/themes/THEME-NAME/ path in CSS and JavaScript references. This tells you whether a site uses a premium theme (Divi, Avada, GeneratePress) or a custom build.
Check the hosting provider
StackPeek detects hosting providers alongside WordPress. Knowing whether a site is on WP Engine, Kinsta, SiteGround, or shared hosting gives you insight into their infrastructure investment and budget.
Use Cases for WordPress Detection
- Agency onboarding: Instantly audit a new client's WordPress setup, plugins, and hosting before your first meeting
- Lead qualification: Filter a prospect list to only WordPress sites if you sell WordPress services or plugins
- Security scanning: Scan thousands of domains to find WordPress sites running outdated versions or vulnerable plugins
- Market research: Determine what percentage of websites in a specific niche use WordPress vs other CMS platforms
- Competitive intelligence: Discover what plugins and themes your competitors are using and how they compare to your choices
- Migration planning: Identify WordPress sites that could benefit from migrating to a modern stack, and pitch your services
Try StackPeek free
Detect WordPress, plugins, themes, and 120+ technologies. 100 scans/day, no API key required.
Try the live scanner →Frequently Asked Questions
Can I detect headless WordPress?
Headless WordPress (WP as a backend with a separate frontend like Next.js or Gatsby) is harder to detect because the HTML served to users does not contain wp-content or wp-includes paths. StackPeek checks the /wp-json/ endpoint as a fallback, which catches most headless setups. However, some headless implementations proxy the REST API through a different path, making detection less reliable.
How accurate is WordPress detection?
For traditional WordPress sites, detection accuracy is extremely high — close to 99%. The wp-content and wp-includes directory paths are unique to WordPress and almost never produce false positives. StackPeek combines multiple signals and returns a confidence score, so you can programmatically handle edge cases.
Can sites hide that they use WordPress?
Yes, but it requires significant effort. Removing the meta generator tag is easy, but rewriting all wp-content and wp-includes URLs requires a dedicated plugin or server-level rewrites. Very few sites go this far. In practice, if a site is actively trying to hide WordPress, it is usually a security measure — and the wp-json endpoint often remains accessible.
What is the rate limit on the free tier?
StackPeek's free tier allows 100 scans per day with no API key required. For higher volume, paid plans start at $9/month for 5,000 scans. See the StackPeek homepage for full pricing details.
Summary
Detecting WordPress programmatically comes down to checking for well-known file paths (wp-content, wp-includes), meta tags, and API endpoints. You can build this yourself with a few lines of code, or use the StackPeek API to get WordPress detection plus the full technology stack in a single call with confidence scores.
For one-off checks, the manual approach works fine. For anything at scale — scanning hundreds of domains, integrating into a product, or building automation — an API saves you time and maintenance headaches.
Related reading: How to detect a website's framework programmatically, How to detect any website's tech stack with a single API call, and Website technology lookup API: the complete developer guide.