# Website Contacts & Tech Stack: Emails, Phones, CMS (`brasspage/website-contact-tech-audit`) Actor

Returns one row per website: public emails, phone numbers and social links from the site itself, plus CMS or builder, analytics and ad pixels, HTTPS, mobile viewport, copyright year and an outdated-site score with reasons. Input: domains or URLs. No browser, obeys robots.txt. $4 per 1,000 sites.

- **URL**: https://apify.com/brasspage/website-contact-tech-audit.md
- **Developed by:** [Brasspage](https://apify.com/brasspage) (community)
- **Categories:** Lead generation, SEO tools, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 site auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Website contacts and tech stack: emails, phones, social links, CMS and pixels from any website

Paste a list of websites. For each one, get the **public contact details the company shows on its own site** and a **quick tech and health audit**, in one row.

### What you get

- **Contacts:** public emails, phone numbers, and social profile links (Facebook, Instagram, X, LinkedIn, YouTube, TikTok, Pinterest, Yelp, Threads).
- **Tech stack:** CMS or website builder (WordPress, Wix, Squarespace, GoDaddy Website Builder, Shopify, Webflow, FrontPage, Joomla, Drupal) and the raw `generator` tag.
- **Analytics and ad pixels:** Google Analytics 4, retired Universal Analytics, Google Tag Manager, Google Ads, Meta Pixel, LinkedIn Insight Tag, TikTok Pixel, X Pixel, Pinterest Tag, Snap Pixel, Microsoft Clarity, Microsoft Advertising UET, Hotjar, HubSpot, Matomo, Plausible, Segment.
- **Site health:** final URL after redirects, HTTPS status, mobile viewport, HTML page weight, load time, copyright year.
- **Outdated-site score** with plain reasons, for example "no viewport meta (not mobile-friendly)", "copyright 2012", "table layout", "uses Flash", "built with Microsoft FrontPage".

**Polite and light.** The Actor reads robots.txt, the homepage and at most 2 contact or about pages per site. No browser, no proxies, no login. **$4 per 1,000 sites.**

### Quick start

1. Paste domains or URLs into **Websites**, one per line.
2. Click **Start**. The 3 prefilled sites finish in a few seconds.
3. Download the table as CSV or Excel and sort it by `outdatedScore`.

### What can you do with it?

- **Lead qualification:** sort a list of prospects by outdated score. A site with no HTTPS, no mobile layout and a 2014 copyright is a warm lead for a redesign.
- **Agency prospecting:** find businesses on Wix, GoDaddy Website Builder or old WordPress, with no analytics or no Meta Pixel, and reach them at the email or phone they publish.
- **Tech stack detection:** see which CMS, builder, analytics and ad pixels a list of companies use. Good for market maps, competitor research and SaaS sales lists.
- **Contact discovery from a company's own website:** you have domains (from a CRM, a directory export, or a Google Maps scrape). Get the emails, phones and social profiles each company shows on its own site.
- **CRM enrichment and cleanup:** find dead sites, parked domains, and sites that redirect to a new domain.
- **AI agents:** call the Actor as a tool (Apify API or Apify MCP server) to answer "Which of these 50 dentists still have a site that is not mobile-friendly?".

### How to use it

1. Add websites to **Websites (URLs or domains)**, one per line: `example.com`, `www.example.com` or `https://example.com/shop`.
2. Click **Start**.
3. Download the results as JSON, CSV, Excel or HTML, or read them through the API.

The Actor always tries HTTPS first, and falls back to HTTP only when HTTPS is broken or missing (that is then reported in `httpsIssue`).

### Input example

```json
{
    "urls": ["https://www.allbirds.com", "https://www.lingscars.com", "https://www.spacejam.com/1996/"]
}
```

| Field  | What it does                                                                                           |
| ------ | ------------------------------------------------------------------------------------------------------ |
| `urls` | Required. Domains or http(s) URLs. Duplicates are removed. Other schemes (mailto:, file:) are ignored. |

### Output example

One item per website:

```json
{
    "inputUrl": "https://www.lingscars.com",
    "url": "https://www.lingscars.com/",
    "domain": "lingscars.com",
    "status": "ok",
    "httpStatus": 200,
    "title": "LINGsCARS.com: Car Leasing, Business & Personal Deals",
    "httpsOk": true,
    "httpsIssue": null,
    "hasMobileViewport": true,
    "pageWeightBytes": 137593,
    "loadTimeMs": 207,
    "copyrightYear": null,
    "tech": [],
    "generator": null,
    "analytics": ["Google Analytics 4", "Google Universal Analytics (retired)"],
    "socialLinks": {
        "facebook": "https://www.facebook.com/lingscars",
        "x": "https://x.com/LINGsCARS",
        "instagram": "https://www.instagram.com/lings_cars",
        "linkedin": "https://www.linkedin.com/company/lingscars-com",
        "youtube": "https://www.youtube.com/@LINGsCARS"
    },
    "emails": ["sales@lingscars.com"],
    "phones": ["0191 460 9444"],
    "outdatedScore": 0,
    "isOutdated": false,
    "outdatedReasons": [],
    "pagesRead": ["https://www.lingscars.com/", "https://www.lingscars.com/about-us/"],
    "auditedAt": "2026-10-15T08:00:11.659Z"
}
```

The 1996 Space Jam site in the same run returns `"outdatedScore": 9` with the reasons `no viewport meta (not mobile-friendly)`, `copyright 1996`, `table layout` and `font/center tags`. The Allbirds store returns `"tech": ["Shopify"]`, `help@allbirds.com` and a phone number.

#### Field notes

| Field                              | Meaning                                                                                                                                                                                                                             |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`                           | `ok` (audited), `skipped` (robots.txt disallows, or the site refuses automated visits with HTTP 401, 403 or 429), or `error` (does not resolve, does not load, not HTML).                                                           |
| `url`, `domain`                    | The final homepage URL after redirects, and its domain without `www.`.                                                                                                                                                              |
| `httpsOk`, `httpsIssue`            | `httpsOk` is `true` when the homepage loads over HTTPS with a valid certificate. Otherwise `httpsIssue` says why: certificate error, HTTPS not available, or plain HTTP.                                                            |
| `hasMobileViewport`                | The homepage has a `<meta name="viewport">` tag, the basic sign of a mobile-friendly layout. When the plain fetch has none, the homepage is read again as an iPhone, because many builders and m. sites send phones their own page. |
| `pageWeightBytes`, `loadTimeMs`    | Size of the homepage HTML (uncompressed, without images and scripts) and the time to download it, redirects included.                                                                                                               |
| `copyrightYear`                    | Newest year in the copyright line (for "© 2009-2016" it is 2016). `null` if none.                                                                                                                                                   |
| `tech`, `generator`                | CMS or builder found from the generator tag, known asset paths and response headers. `generator` is the raw tag, which also names other tools (Elementor, Hugo, ...).                                                               |
| `analytics`                        | Analytics and ad pixels found in the HTML of the pages read.                                                                                                                                                                        |
| `emails`                           | Emails shown on the pages read, the site's own domain first. Includes `mailto:` links, "name \[at] domain" text and Cloudflare-protected addresses.                                                                                  |
| `phones`                           | `tel:` links first, then phone numbers in the visible text (North American format, or international with a `+` country code).                                                                                                       |
| `outdatedScore`, `outdatedReasons` | Points for each sign of an old site. `isOutdated` is `true` at 3 or more (one strong sign, or two weaker ones). See the table below.                                                                                                |
| `pagesRead`                        | Every page the Actor read for this site (homepage plus up to 2 contact or about pages).                                                                                                                                             |

#### How the outdated score works

| Points | Signal                                                                                                                                                                     |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 4      | Broken site, or a parked / for-sale domain                                                                                                                                 |
| 3      | No mobile viewport, uses Flash, "under construction" or "coming soon", copyright 2014 or older                                                                             |
| 2      | No HTTPS or a broken certificate, copyright 2015-2019, table layout, frames, built with an old editor (FrontPage, Dreamweaver, iWeb, Publisher, ...)                       |
| 1      | jQuery 1 or 2, WordPress 4 or older, Bootstrap 2 or 3, only the retired Universal Analytics, `<font>` / `<center>` tags, HTML 4 doctype, slower than 5 s, HTML over 1.5 MB |

### Pricing

Pay per event. You pay only for sites that were audited.

| Event        | Price                              |
| ------------ | ---------------------------------- |
| Site audited | **$0.004 per site** ($4 per 1,000) |
| Actor start  | $0.00005 per run (Apify default)   |

Sites that robots.txt blocks, that refuse automated visits, or that do not load are **free**. Example: 500 domains with 450 audited cost $1.80. Set **Max cost per run** in the run options and the Actor stops at that amount.

**Apify free plan:** each run audits the first **10 sites**, so you can try the Actor on your own list. Upgrade to a paid Apify plan to audit every site in one run.

### FAQ

**Where does the data come from?** Only from each website itself: its robots.txt, its homepage and at most 2 of its own contact or about pages. Everything in the output is something the company publishes on its own site.

**What does it not do?**

- **No personal data enrichment.** The Actor does not look people up, guess email patterns, verify inboxes, or join data from other sources. If an address or phone number is not shown on the site, it is not in the output.
- **No third-party scraping.** It does not read Google, LinkedIn, Facebook, Yelp or any directory. Social links are the links the site itself shows; the Actor never opens them.
- **No crawling.** At most 3 pages per site. It does not follow links beyond one contact page and one about page.
- **No bypassing.** No proxies, no browser fingerprinting, no CAPTCHA solving. A site that says no gets `status: "skipped"`.

**Does it respect robots.txt?** Yes. It reads robots.txt first and skips any page it disallows for its user agent (`SiteAuditBot`) or for all bots. If robots.txt returns a server error, the whole site is skipped. If a site answers HTTP 401, 403 or 429, the Actor stops there.

**How fast and how polite is it?** Each host gets at most 1 request per second and each request times out after 10 seconds. Different sites run in parallel, so 1,000 sites take a few minutes.

**Is it safe to give it any URL?** It accepts only http and https addresses on the public internet. Every redirect is checked, and requests to private, loopback or link-local addresses are refused.

**Is the contact data GDPR-compliant to use?** The Actor returns only what each company publishes on its own website. Some published emails can belong to a named person. You decide how you use them; follow GDPR, CAN-SPAM and the other laws that apply to you.

**Why are emails or phones empty for a site?** The site may show contacts only in images, in a contact form, or on a page the Actor did not read. Pages that load their content with JavaScript only (single-page apps) may also show little in the HTML.

**Why was a site skipped?** `skipReason` says why: robots.txt disallows the page, or the site refused automated visits. These sites are not charged.

**Can I use it from code or an AI agent?** Yes. Call it with the Apify API, the JavaScript or Python client, or the Apify MCP server. The output is flat JSON that exports cleanly to CSV. To give an AI agent this one tool, connect it to the Apify MCP server at `https://mcp.apify.com?tools=brasspage/website-contact-tech-audit`.

**Missing a CMS, pixel or field?** Tell us in the Issues tab.

### Related Actors

Other tools from the same developer, with the same pay-per-result pricing:

- [ATS Jobs API](https://apify.com/brasspage/careers-site-jobs-api): every open job from Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Recruitee and Personio boards, with new-job alerts.
- [Podcast & Audio Transcriber](https://apify.com/brasspage/media-transcriber): podcast episodes and audio or video files to text, SRT and VTT for $0.004 per minute.
- [Google Sheets Export & Sync](https://apify.com/brasspage/google-sheets-sync): send the results of any Actor to a Google Sheet (append, replace or upsert).
- [PDF OCR to Markdown](https://apify.com/brasspage/pdf-ocr-to-markdown): scanned PDFs and images to clean Markdown with tables, for $0.006 per page.

# Actor input Schema

## `urls` (type: `array`):

One website per line: a domain (example.com) or a URL (https://www.example.com). The Actor always tries HTTPS first. It reads robots.txt, the homepage, and at most 2 contact or about pages of each site. On the Apify free plan, a run audits the first 10 sites.

## Actor input object example

```json
{
  "urls": [
    "https://www.allbirds.com",
    "https://www.lingscars.com",
    "https://www.spacejam.com/1996/"
  ]
}
```

# Actor output Schema

## `sites` (type: `string`):

One item per website: final URL, HTTPS, mobile viewport, page weight, load time, copyright year, CMS or builder, analytics and pixels, social links, public emails and phones, outdated score with reasons. Skipped and unreachable sites say why.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.allbirds.com",
        "https://www.lingscars.com",
        "https://www.spacejam.com/1996/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("brasspage/website-contact-tech-audit").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "urls": [
        "https://www.allbirds.com",
        "https://www.lingscars.com",
        "https://www.spacejam.com/1996/",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("brasspage/website-contact-tech-audit").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.allbirds.com",
    "https://www.lingscars.com",
    "https://www.spacejam.com/1996/"
  ]
}' |
apify call brasspage/website-contact-tech-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,brasspage/website-contact-tech-audit"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/cagccUgvPG4Dc37SB/builds/OVFlkQBhyvdutvp96/openapi.json
