# Trade Show Exhibitor Scraper: First-Time & Lapsed (`sullivan-ventures/exhibitor-scraper`) Actor

Get any trade show's exhibitor list (Map Your Show, a2z or plain HTML) with first-time exhibitors scored high/medium/low, lapsed exhibitors from last year, startup and new-product badges, booths and websites. CSV, Excel, JSON. US and international shows.

- **URL**: https://apify.com/sullivan-ventures/exhibitor-scraper.md
- **Developed by:** [Michael Sullivan](https://apify.com/sullivan-ventures) (community)
- **Categories:** Lead generation, Marketing, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 exhibitor rows

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

## Trade Show Exhibitor Scraper: First-Time & Lapsed

Trade Show Exhibitor Scraper is an Apify Actor by Sullivan Ventures that exports a trade show's public exhibitor list (Map Your Show, a2z or plain HTML) and flags first-time exhibitors with a high, medium or low confidence level, lapsed exhibitors from last year, and organizer badges like Startup and New Products. It's built for booth builders, promo-product sellers and event agencies who want to reach new exhibitors before they choose vendors.

Turn any trade show's exhibitor directory into a lead list that tells you **who is new, who dropped out, and who is spending**:

- **First-time exhibitors with a confidence level.** Two sources: the organizer's own "First Time Exhibitor" badge and a year-over-year comparison with last year's list. Each row says `high`, `medium` or `low`, so you can call the sure ones first.
- **Startup and new-product badges.** Map Your Show organizers tag exhibitors as Startup, Offering New Products, association members and featured (paid) listings. Other scrapers throw these away; this one keeps them.
- **Lapsed exhibitors.** Companies that were at last year's show but are not on this year's list: a ready win-back list.
- Plus the basics: company, booth, website, category, city, state, country, sponsor-only flag. CSV, Excel or JSON.

#### Who uses it

| You sell... | Use it to... |
| --- | --- |
| Booth design, rentals, graphics, printing | Reach first-time exhibitors before they pick a vendor; win back lapsed ones |
| Promo products, giveaways, booth staffing, AV, lead retrieval, shipping, hotels | Target startups and first-timers who have budget but no habits yet |
| Event / exhibit marketing agency services | Find featured-listing and new-product exhibitors who are actively spending |
| B2B software or services (sales teams) | Book pre-show meetings with the right booths, with booth numbers in your email |

#### Real numbers from test runs

- NAB Show 2026: 1,127 exhibitors; the organizer badges 212 as First Time Exhibitor, 152 Offering New Products, 33 Startup, 150 featured listings.
- PACK EXPO International 2026 vs 2024: 2,716 exhibitors, 956 not at the 2024 show (live lists on both years, so `high` confidence), and 929 lapsed 2024 exhibitors.

### Why first-time exhibitors?

First-time exhibitors are the warmest leads at any show. They have new budgets, no booth vendor yet, no favorite hotel block, no freight company, no lead-retrieval habit. Organizers rarely publish the list. This Actor builds it for you.

### Quick start

1. Paste the show's exhibitor list link (for Map Your Show it ends in `/8_0/explore/exhibitor-gallery.cfm`).
2. Optional but recommended: paste last year's link in **Last year's directory URLs** (for Map Your Show, usually the same link with last year's 2 digits, e.g. `packexpo24` instead of `packexpo26`).
3. Run. Filter the table by `first_time_confidence`, `startup` or `new_products`. Get lapsed exhibitors from the Storage tab (`LAPSED_CSV`).

### Supported directories

| Platform | Example link | What you get |
| --- | --- | --- |
| Map Your Show | `https://packexpo26.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm` | Company, booth, description. With "Include details": website, city, state, country, product categories (when the show makes them public). |
| a2z / Personify | `https://hd.a2zinc.net/HDExpo2026/Public/Exhibitors.aspx` | Company, booth, profile link. |
| Any HTML list | any page | Whatever your CSS selectors point at (name, booth, website, category, location), with next-page support. |

### Input example

```json
{
  "startUrls": [{ "url": "https://packexpo26.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm" }],
  "previousYearUrls": [{ "url": "https://packexpo24.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm" }],
  "onlyFirstTime": true,
  "includeLapsed": true,
  "includeDetails": false
}
```

Real result for this input: 2,716 exhibitors at PACK EXPO International 2026, 956 of them not at the 2024 show, and 929 lapsed 2024 exhibitors.

### Output example

```json
{
  "company": "16x9, Inc.",
  "booth": "C8040",
  "website": "https://www.16x9inc.com",
  "category": "Audio Production, Processing and Networking; Cameras, Camera Support Control and Accessories; Lighting and Grip",
  "city": "Burbank",
  "state": "California",
  "country": "United States",
  "show": "2026 NAB Show",
  "year": 2026,
  "is_first_time": false,
  "first_time_source": null,
  "first_time_confidence": null,
  "exhibitor_status": "returning",
  "organizer_first_time": false,
  "first_time_by_comparison": null,
  "organizer_badges": ["NAB Associate Member"],
  "startup": false,
  "new_products": false,
  "featured_listing": false,
  "sponsor_only": false,
  "platform": "mapyourshow",
  "profile_url": "https://nab26.mapyourshow.com/8_0/exhibitor/exhibitor-details.cfm?exhid=8800198"
}
```

Download as CSV, Excel or JSON from the Output tab.

### First-time flag: two sources and a confidence level

- `first_time_by_comparison`: `true` when the company is not on last year's list (needs `previousYearUrls`), else `false`/`null`.
- `organizer_first_time`: `true`/`false` from the organizer's "First Time Exhibitor" badge, or `null` when the show doesn't publish that badge (many don't, e.g. PACK EXPO 2026 has none, NAB Show 2026 does).
- `is_first_time`: `true` if either source says first-time, `false` if the sources say returning, `null` if there's no source at all.
- `first_time_source`: `organizer+comparison`, `organizer` or `comparison`.
- `first_time_confidence`:
  - `high`: both sources agree, or the comparison used a live (complete) last-year list on a show with no organizer badge.
  - `medium`: only the organizer badge says so, or the comparison used an archived last-year list with good coverage, or the comparison was live but the organizer didn't badge them.
  - `low`: only the comparison says so, last year came from the Wayback Machine, and either the archive was incomplete or the organizer didn't badge them. These are often repeat exhibitors the archive missed.
- `exhibitor_status`: `first_time`, `returning`, or `lapsed` (lapsed rows only appear with `lapsedInDataset`).
- Without `previousYearUrls`, shows that publish the badge still get first-time flags (source `organizer`).

### Organizer badge fields (Map Your Show)

- `organizer_badges`: every badge on the listing, as the show names them (for example "NAB Associate Member", "PMMI Member", "Machinery On-Site", "Green Exhibitor").
- `startup`, `new_products`: `true`/`false` when the show uses a Startup / Offering New Products badge, `null` when it doesn't.
- `featured_listing`: the exhibitor has a featured listing in the directory (usually a paid upgrade, a sign of marketing budget).
- `sponsor_only`: listed as a sponsor without a floor booth.
- On a2z and generic lists these fields are `null` (`sponsor_only` still works from the booth text).

### Lapsed exhibitors (win-back list)

With `previousYearUrls`, the run also saves companies that were at last year's show but are not in this year's directory to the key-value store as `LAPSED` (JSON) and `LAPSED_CSV` (open it from the Storage tab). Turn on `lapsedInDataset` to add them to the main dataset as `exhibitor_status = lapsed` rows. The run SUMMARY has the count.
Read before using: early in a show's sales cycle, some lapsed companies simply haven't signed up yet, and a company that renamed itself can appear as lapsed (old name) and first-time (new name). Example: PACK EXPO 2026 vs 2024 gave 929 lapsed exhibitors.

### How the comparison works

Company names are normalized (case, punctuation, accents, and endings like Inc, LLC, Ltd, GmbH are ignored), and on Map Your Show the exhibitor ID is matched too. So "Acme Packaging, Inc." in 2026 matches "ACME PACKAGING" in 2024. Biennial shows work: just give the last edition (for example 2024 for a 2026 show).

### Wayback Machine fallback (when last year's directory is gone)

Show organizers often take last year's exhibitor directory offline. When a URL in **previousYearUrls** (or startUrls) fails or returns zero exhibitors, the Actor looks for archived copies on the Internet Archive's Wayback Machine:

1. It asks the Wayback CDX index (`web.archive.org/cdx/search/cdx`) which copies of that directory exist.
2. Map Your Show: it first uses archived copies of the JSON search API (full records, booths included), then archived exhibitor profile pages (one exhibitor per page). Archived gallery pages are only an empty shell, so they're used just for the show name.
3. a2z / Personify and generic pages: it fetches archived copies of the list page, including category-filtered versions, and merges them.
4. When a page was archived several times, it uses the copy nearest the show's year (skipping truncated copies).
5. Archived pages are downloaded in raw (`id_`) mode and parsed with the same parsers used for live pages.

Rows and the run summary show where the data came from:

- `source`: `live` or `wayback`
- `snapshot`: date range of the archived copies used (e.g. `2025-05-15 to 2025-12-15`)
- `prev_year_source` / `prev_year_snapshot`: same thing for the year you compared against
- `prev_year_coverage` / `prev_year_warning`: when last year came from the Wayback Machine, coverage is last year's recovered count divided by this year's count. If it is under 70%, every row and the run's SUMMARY (`warnings`) say the first-time count is likely too high, because the archive missed some of last year's exhibitors.

Inputs: `waybackFallback` (on by default), `maxWaybackPages` (max archived pages per show, default 500), `waybackMaxMinutes` (time budget per show, default 10).

**Limits, read before trusting the first-time flag:**

- Archives are partial. If only part of last year's list was archived, exhibitors that were missed look "first-time". Check `prev_year_source` and the SUMMARY's archive coverage numbers.
- The Wayback Machine rate-limits heavy use, so the Actor fetches slowly (about one page every 4 seconds). Recovering a big Map Your Show list from profile pages can take an hour. Raise `waybackMaxMinutes` if you need full coverage. The Actor follows archive.org's published limits: at most 48 requests a minute, a clear User-Agent, and a full stop of 60 seconds or more whenever archive.org says slow down (HTTP 429). It never switches IPs to get around a limit, and it stops using Wayback for the run after 3 slow-downs in a row. The Wayback fallback is only for shows whose terms allow collecting their exhibitor list.
- Many a2z directories were never archived. The Actor then stops with a clear message instead of pretending everyone is new.

### Tips

- Use the show's English exhibitor list page.
- "Include details" opens every exhibitor profile, so it is slower. Leave it off if you only need names and booths.
- `maxItems` limits how many of this year's exhibitors are checked (handy for a quick test).

### Pricing

Pay per event: $3.00 per 1,000 exhibitor rows ($0.003 per row), plus $0.20 once per run when you compare with a prior year. No start fee. Plus your normal Apify platform usage, which is small. A 1,127-exhibitor show like NAB Show 2026 costs about $3.38 in row fees. Set a max cost per run to cap spend, and use `maxItems` for a quick test run.

### FAQ

#### How do I find first-time exhibitors at a trade show?

Run this Actor with the show's exhibitor-directory URL. It reads the organizer's own "First Time Exhibitor" badge when there is one and compares this year's list with last year's. Each row gets a high, medium or low confidence level. On NAB Show 2026 the organizer badged 212 of 1,127 exhibitors as first-timers.

#### Can I get a list of exhibitors who didn't come back this year?

Yes. Give the Actor last year's directory URL. Companies on last year's list that are missing from this year's come out as lapsed exhibitors. On PACK EXPO International 2026 vs 2024 that was 929 companies, a ready win-back list for booth and service vendors.

#### Which exhibitor directories does it support?

Map Your Show, a2z (Personify) and simple HTML exhibitor pages. It reads only public pages that open without a login. If a show's terms bar collecting its exhibitor list, don't run it on that show.

#### How much does it cost to scrape an exhibitor list?

Pay per result: $3.00 per 1,000 exhibitor rows, plus $0.20 when you run a year-over-year comparison, plus normal Apify platform usage. A 1,127-exhibitor show like NAB 2026 costs about $3.38 in row fees. Set a maximum cost per run to cap spend.

#### What if last year's exhibitor list is no longer online?

For shows whose terms allow collecting the list, the Actor can rebuild last year's list from Wayback Machine snapshots. It keeps archive.org's published limits: at most 48 requests a minute, a clear User-Agent, and a 60-second or longer pause on any slow-down. Confidence is marked lower for archived lists.

#### Which trade shows and countries does it cover?

Any trade show, in the US or abroad, whose public exhibitor directory runs on Map Your Show, a2z or plain HTML and whose terms allow collecting the list. NAB Show and PACK EXPO are only test examples. Coverage: we confirm data availability for your show before you run it; ask in the Issues tab.

### Is it legal?

This Actor reads only public exhibitor directories that anyone can open without logging in. You are responsible for how you use the data and for following each show's terms.

# Actor input Schema

## `startUrls` (type: `array`):

One or more exhibitor list pages. Map Your Show (…mapyourshow.com/8_0/explore/exhibitor-gallery.cfm), a2z / Personify (…a2zinc.net/…/Public/Exhibitors.aspx), or any HTML list (set the CSS selectors below).

## `previousYearUrls` (type: `array`):

Optional. The same show's previous edition. Every row gets is_first_time by comparing company names (and Map Your Show exhibitor IDs), combined with the organizer's own First Time Exhibitor badge when the show publishes one. Also builds the lapsed-exhibitor list.

## `onlyFirstTime` (type: `boolean`):

Output only first-time exhibitors (from the last-year comparison and/or the organizer's First Time Exhibitor badge).

## `includeLapsed` (type: `boolean`):

When last year's URL is given, also list companies that were at last year's show but are not in this year's directory. Saved to the key-value store as LAPSED (JSON) and LAPSED_CSV. With maxItems set, the full Map Your Show list is still read (cheap) so the check stays correct.

## `lapsedInDataset` (type: `boolean`):

Adds lapsed companies as extra rows with exhibitor_status = lapsed (each counts as a result).

## `waybackFallback` (type: `boolean`):

If a directory is offline (common for last year's show), recover it from archive.org's Wayback Machine. Rows are marked source = wayback with the snapshot date.

## `maxWaybackPages` (type: `integer`):

Upper limit on archived pages fetched per directory (archived exhibitor profile pages count one each). Higher = more coverage, slower run.

## `waybackMaxMinutes` (type: `integer`):

Stop fetching archived pages after this many minutes per directory and use what was recovered.

## `includeDetails` (type: `boolean`):

Map Your Show only for now: opens each exhibitor profile. Slower. Without it you get company, booth and description from the list.

## `maxItems` (type: `integer`):

How many of this year's exhibitors to output (0 = all). The form starts at 100 for a quick, cheap first run; set 0 to get the whole show. The comparison and lapsed list still use the full lists.

## `platform` (type: `string`):

Leave on auto unless detection fails.

## `showName` (type: `string`):

Optional. Otherwise taken from the page title.

## `itemSelector` (type: `string`):

Generic: CSS selector for one exhibitor row.

## `nameSelector` (type: `string`):

Generic: company name selector (inside row).

## `boothSelector` (type: `string`):

Generic: booth selector (inside row).

## `websiteSelector` (type: `string`):

Generic: website link selector (inside row).

## `categorySelector` (type: `string`):

Generic: category selector (inside row).

## `locationSelector` (type: `string`):

Generic: location selector (inside row).

## `nextPageSelector` (type: `string`):

Generic: next-page link selector.

## `maxPages` (type: `integer`):

Generic: max pages.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://packexpo26.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm"
    }
  ],
  "previousYearUrls": [
    {
      "url": "https://packexpo24.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm"
    }
  ],
  "onlyFirstTime": false,
  "includeLapsed": true,
  "lapsedInDataset": false,
  "waybackFallback": true,
  "maxWaybackPages": 500,
  "waybackMaxMinutes": 10,
  "includeDetails": false,
  "maxItems": 100,
  "platform": "auto",
  "maxPages": 20
}
```

# Actor output Schema

## `exhibitors` (type: `string`):

One row per exhibitor: company, booth, website, location, is_first_time with source and confidence, organizer badges, startup/new-product flags.

## `lapsed` (type: `string`):

Companies on last year's list that are not in this year's directory.

## `lapsedCsv` (type: `string`):

Same lapsed list as CSV.

## `summary` (type: `string`):

Per-show counts: exhibitors, first-time by confidence, lapsed, prior-year coverage and warnings.

# 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 = {
    "startUrls": [
        {
            "url": "https://packexpo26.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm"
        }
    ],
    "previousYearUrls": [
        {
            "url": "https://packexpo24.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm"
        }
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("sullivan-ventures/exhibitor-scraper").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 = {
    "startUrls": [{ "url": "https://packexpo26.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm" }],
    "previousYearUrls": [{ "url": "https://packexpo24.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm" }],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("sullivan-ventures/exhibitor-scraper").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 '{
  "startUrls": [
    {
      "url": "https://packexpo26.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm"
    }
  ],
  "previousYearUrls": [
    {
      "url": "https://packexpo24.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm"
    }
  ],
  "maxItems": 100
}' |
apify call sullivan-ventures/exhibitor-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sullivan-ventures/exhibitor-scraper"
        }
    }
}
```

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/aWkSplspU1Zy13pbQ/builds/j8sp3ljzIPnYcV5ca/openapi.json
