# Thomasnet Suppliers Scraper - US & Canada Manufacturers (`amitaviv/thomasnet-suppliers-scraper`) Actor

Scrape Thomasnet industrial suppliers and manufacturers in the USA and Canada by product or service, ZIP/postal code, US state or Canadian province: company type, address, phone, website, sales and employee bands, year founded, categories. Only-new monitoring. $4 per 1,000 suppliers on Bronze.

- **URL**: https://apify.com/amitaviv/thomasnet-suppliers-scraper.md
- **Developed by:** [Amit Aviv](https://apify.com/amitaviv) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.20 / 1,000 suppliers

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Thomasnet Suppliers Scraper: US & Canadian Manufacturers, Distributors & Service Companies

US and Canadian industrial suppliers from Thomasnet (thomasnet.com) for a product or service keyword, nationwide, around ZIP or postal codes, or across whole US states and Canadian provinces: company type, address, phone, website, annual sales and employee bands, year founded, categories, materials and industries served. It reads Thomasnet's public pages over plain HTTP (no browser), you pay only for suppliers delivered, and a run that delivers nothing because of an error or a block ends as Failed, never as a green empty run.

### What you get

- Company name, primary company type (Manufacturer, Custom Manufacturer, Distributor, Service Company, Finishing Service Company, Manufacturers' Rep, Turnkey Systems Integrator, ...) and other activities it lists
- Street address, city, state or province, ZIP or postal code, country, latitude and longitude; distance from the searched ZIP or postal code. For companies with several locations (`isMultiLocation: true`) Thomasnet's search card shows either the main location's address or a branch's, and the distance is to the location nearest the search, which is not always the address shown; the actor delivers the card as Thomasnet shows it
- Phone number as listed on Thomasnet, and website. For advertisers the listed phone is usually a Thomasnet call-tracking number that forwards to the company (in our checks of 6 advertisers it differed from the number on the company's own website); branches of multi-location companies often show the main location's number
- Annual sales band, employee band, year founded
- The Thomasnet categories that matched your search (a search card shows up to 5), the category that matched best, materials worked, industries served, production scale (prototype, short run, high volume, ...)
- Listing flags: Thomasnet tier (e.g. VERIFIED), advertiser, claimed profile, top responder, Xometry partner, branch of a multi-location company
- With **Add company profile details**: the category headings the public profile page lists (`allCategories`, up to 25; Thomasnet's "Company Profile Section" placeholder heading is left out), the company's own description, how many certifications it lists by type (quality, registration, diversity), social media and blog links, and its Thomasnet product families
- One record per supplier, as JSON, CSV or Excel, or through the API. A supplier found by several searches in one run is delivered and charged once, with the address, distance and search fields of the first search that found it.
- A run summary (`OUTPUT_SUMMARY` in the run's key-value store): what was requested, delivered and charged; per search how many suppliers Thomasnet reports and how many it shows; which inputs failed or were ignored and why; whether the run moved to residential proxy; why the run stopped.

What it does not return: certification names and ownership/diversity status (Thomasnet shows them only to signed-in users; you get the counts), key personnel and other named employees, emails, press releases, anything behind Thomasnet's login.

### How Thomasnet limits visitors, and how the actor deals with it

Thomasnet shows a visitor who is not signed in the first page of a search: about 25 suppliers, in Thomasnet's own ranking (advertisers first). The second page and every filter (company type, certification, location served) ask the visitor to register. This actor does not sign in, so:

- A nationwide search returns about 25 suppliers per term (in run `3Tum7zbNfK5UFlSWt` Thomasnet reported 7,199 suppliers for "gear cutting" and showed 26, of which 25 were distinct).
- **ZIP codes** narrow a search to an area, the way Thomasnet's own location box does: about 25 suppliers per term per ZIP code, all near it.
- **States** run one ZIP-code search per main industrial city of the state (1 to 13 cities, e.g. 11 for Texas, 8 for New Jersey, 5 for Rhode Island) and keep the suppliers whose address is in the state. In small states and next to state lines each city uses a smaller radius of its own (5 miles in DC, 8-15 in Rhode Island), so the 25 suppliers Thomasnet shows stay mostly in the state. Two terms across Texas gave 317 distinct Texas suppliers in 38 seconds (`tST5NMY13L4UZRS3G`); "cnc machining" in DC and Rhode Island gave 62 (`IL1S1IfA843JY6V27`); "injection molding" in New Jersey and Connecticut gave 138 (`24ESPsfh4dLHvWMjN`). Suppliers found outside the state are skipped, not charged, and counted in the status message.
- **Canadian provinces** work the same way (Ontario 13 cities, Quebec 9, British Columbia 6, Alberta 7, and 1-3 in Manitoba, Saskatchewan, Nova Scotia, New Brunswick, Newfoundland and Labrador, Prince Edward Island). "cnc machining" in Ontario and Alberta plus the Montreal postal code `H4T 1A1` gave 330 distinct suppliers in 34 seconds (`C8e6V0jLLMfp0YU5i`: 227 in Ontario, 78 in Alberta, 25 near Montreal). Canadian postal codes are searched by their first 3 characters (`M5V 2T6` becomes `M5V`), which is what Thomasnet's location box understands; a full postal code finds nothing there.
- More specific terms (e.g. "swiss cnc machining" next to "cnc machining") and more ZIP codes with a smaller radius reach further. The status message says when a search had more suppliers than Thomasnet shows.

### How to use

1. Type what the suppliers make or do into **Products or services**, e.g. `cnc machining`, `injection molding`, `ball valves`. Several entries are fine.
2. Optional: add **Near ZIP / postal codes** (with **Radius**) or **US states / Canadian provinces** (`TX`, `Ohio`, `Washington DC`, `Ontario`, `QC`). Without them, the search is nationwide. For states, raise **Maximum suppliers per search** (it counts per term and state together).
3. Or paste Thomasnet pages into **Thomasnet URLs**: a search URL, a category page (`thomasnet.com/suppliers/usa/cnc-machining-45330503`) or a company profile.
4. Set **Maximum suppliers per search** and press Start. Download the results from the Output tab, or read them from the API.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchTerms` | list of text | none | Products or services, as typed in Thomasnet's search box. One search per term, and per ZIP code or state when given. |
| `startUrls` | list of URLs | none | thomasnet.com search URLs, category pages or company profiles, used as they are (an old-style `what=` search URL is read as `searchterm=`; a URL that repeats one of your terms is fetched once). URLs with filters or a page number above 1 need a Thomasnet account: that search fails with a message saying so (`0fq3g7GJARhSAUpqY`). Other sites' URLs are ignored and listed in the summary. |
| `zipCodes` | list of text | none | US ZIP codes (5 digits) or Canadian postal codes (`M5V 2T6` or `M5V`). Each term is searched around each one. |
| `states` | list of text | none | US states, DC and Canadian provinces by code or name (`TX`, `Texas`, `DC`, `Washington DC`, `ON`, `Ontario`, `Québec`). Each term is searched around the state's or province's main industrial cities; only suppliers with an address there are kept. |
| `radiusMiles` | number | 50 | Radius around each ZIP code or state city, 1-500 miles. Some state cities use a smaller radius of their own (see above). |
| `maxItems` | number | 100 | Stop each search (one term with one ZIP code, one term with one state, or one URL) after this many suppliers. A state search can find a few hundred: raise it for big states. |
| `includeProfileDetails` | yes/no | no | Open each supplier's profile and add the category headings it lists, the company's own description, certification counts, social links and product families. One more page per supplier; no extra charge. |
| `onlyNew` | yes/no | no | Deliver and charge only suppliers earlier runs with the same searches did not deliver. See "Monitoring". |
| `monitorKey` | text | empty | Name of the monitor memory, to keep two schedules apart. |
| `proxyConfiguration` | proxy | off | Not needed: see the FAQ. |

Input values that cannot be used (a ZIP code that is not 5 digits nor a Canadian postal code, a state or province that does not exist, a Canadian territory in `states`) fail the run in about a second, before any charge but the start fee; the message says what to change. Search terms longer than 200 characters are ignored and listed in the summary.

This input was run as `z51scTOrq7YfbWcUN` on 2026-10-20 (60 Ohio suppliers with profile details, 44 seconds):

```json
{
  "searchTerms": ["cnc machining"],
  "states": ["Ohio"],
  "maxItems": 60,
  "includeProfileDetails": true
}
```

### Example result

Taken from run `z51scTOrq7YfbWcUN` on 2026-10-20, unedited:

```json
{
  "id": "30114506",
  "name": "Miles Products, Inc.",
  "supplierType": "Custom Manufacturer",
  "supplierTypeCode": "C",
  "additionalActivities": ["Custom Manufacturer - Instant Quote"],
  "description": "Custom manufacturer of thermoplastics. Capabilities include injection molding, machining, additive manufacturing, 3D printing, and vacuum forming. Additional services such as designing, engineering, labeling, and part decorating are also provided. Prototypes and production runs are available. Serves the commercial trucking, healthcare, medical, and transportation industries.",
  "street": "4492 Vicky Drive",
  "city": "Brunswick",
  "state": "OH",
  "stateName": "Ohio",
  "postalCode": "44212",
  "country": "USA",
  "latitude": 41.23928022,
  "longitude": -81.8322881,
  "phone": "(801) 717-5870",
  "website": "http://milesproducts.com",
  "annualSales": "Under $1 Mil",
  "employees": "1-9",
  "yearFounded": 1986,
  "thomasTier": "VERIFIED",
  "isAdvertiser": true,
  "isClaimed": true,
  "isTopResponder": true,
  "xometryPartner": false,
  "isMultiLocation": false,
  "mainLocationName": null,
  "mainLocationId": null,
  "logoUrl": "https://cdn.thomasnet.com/ccp/30114506/372529.png",
  "profileUrl": "https://www.thomasnet.com/company/miles-products-inc-30114506/profile",
  "categories": ["CNC Machining", "General Contract Machining", "Special Machining", "Machining", "Precision Machining"],
  "matchedCategory": "CNC Machining",
  "materials": ["Acrylonitrile Butadiene Styrene (ABS)", "Aluminum", "Any Metal", "Exotic Metals", "Graphite", "Nylon", "Plastics", "Polycarbonate", "Steel"],
  "industries": ["Aerospace", "Automotive", "Consumer Goods", "Electrical", "Electronics", "Medical and Dental", "Military"],
  "productionScale": ["High Volume", "Low Volume", "Production Runs", "Prototype", "Short Run"],
  "catalogItems": [],
  "distanceMiles": 18.5,
  "allCategories": [],
  "companyDescription": "Since 1979 Miles Products has built its reputation on know-how, service, and reliability. Success demands strategy and teamwork. Our network and dedicated customer service can help your team develop, produce and launch the next big breakthrough. We are dedicated to made in USA and North American manufacturing for the great design, quality and logistics it provides.",
  "certificationCount": 18,
  "certificationCountsByType": { "QUALITY": 6, "DIVERSITY": 1, "REGISTRATION": 11 },
  "socialLinks": [
    { "type": "BLOGS", "url": "https://milesproducts.com/blog" },
    { "type": "YOUTUBE", "url": "https://www.youtube.com/channel/UCkK5aHDa_HbpZ-4IPUW8W9g" }
  ],
  "productFamilies": ["Additive Manufacturing Services", "Assemblies", "Automotive Parts", "Bins", "Casting Services", "Connector Parts", "Connectors", "Containers", "Drafting Services", "Electrical Components", "Electronic Components", "Electronics Contract Manufacturing Services", "Fabrication Services", "Foams", "Food", "Food Contract Manufacturing & Private Labeling", "Forming Services", "Job Shop Services", "Machining", "Manufacturing Services"],
  "locationTypes": [],
  "detailsFetched": true,
  "searchTerm": "cnc machining",
  "searchLocation": "Cleveland, OH (ZIP 44113) +50 mi",
  "searchRank": 15,
  "scrapedAt": "2026-10-20T13:43:47.141Z"
}
```

| Field | Meaning |
|---|---|
| `id` | Thomasnet's company id; stable between runs. |
| `supplierType`, `supplierTypeCode` | Primary company type as Thomasnet lists it, and its one-letter code. |
| `supplierType`, `supplierTypeCode` (null) | Some listings have no primary type; their activities are still in `additionalActivities` (12 of 317 in the Texas run). |
| `phone` | As listed on Thomasnet; for advertisers (`isAdvertiser: true`) usually a call-tracking number that forwards to the company. |
| `annualSales`, `employees` | Bands as Thomasnet shows them (text, e.g. `$5 - 9.9 Mil`, `50-99`); `null` where Thomasnet shows "N/A". |
| `categories` | The Thomasnet categories of this company that matched the search (up to 5 on a search card). |
| `allCategories` | With profile details: the category headings the public profile page lists, each name once, without the "Company Profile Section" placeholder heading that Thomasnet's profile data includes (the page shows at most 25 headings, so up to 25 names; empty when the profile lists none: 4 of 10 profiles in `Ex4mJlCAVMd1dq8xG`); `null` without details. |
| `distanceMiles` | Distance from the searched ZIP or postal code (ZIP and state searches). For multi-location companies it is measured to the location nearest the search, which may not be the address shown. |
| `isMultiLocation` | The company has several locations. Its address may be the main location or a branch, as Thomasnet's card shows it; in a state search a company is kept only if the address shown is in the state, so a company whose card shows an out-of-state main address is skipped there even if it has a branch in the state. |
| `certificationCount`, `certificationCountsByType` | With profile details: how many certifications the profile lists, by type. Names are for signed-in users only. |
| `searchTerm`, `searchLocation`, `searchRank` | Which search found the supplier (its term, and the ZIP/postal code or city searched; `searchLocation` is `null` for a nationwide search), and its position in Thomasnet's ranking for that search. For a pasted search URL they come from the URL (`searchterm`, and `zip` + `radius` when present); for a pasted category page or profile `searchTerm` and `searchLocation` are `null`. |
| `detailsFetched` | `true` when the profile details were added. |

Fields the site does not provide for a given supplier are `null` (or an empty list), never missing; Thomasnet's "N/A" and "NONE" placeholders are `null` too. Fill rates with real values:

| Field | Ohio, 60 suppliers with details (`z51scTOrq7YfbWcUN`) | Texas, 317 suppliers (`tST5NMY13L4UZRS3G`) |
|---|---|---|
| Phone | 60 (100%) | 302 (95%) |
| Street, coordinates | 60 (100%) | 317 (100%) |
| Website | 54 (90%) | 233 (74%) |
| Annual sales band | 47 (78%) | 190 (60%) |
| Employee band | 49 (82%) | 221 (70%) |
| Year founded | 51 (85%) | 212 (67%) |
| Company's own description (details only) | 33 (55%) | not requested |

### Pricing

Pay per event. You pay for suppliers delivered, not for time, memory or proxy traffic.

| Event | Free | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Actor start (once per run at the default 256 MB) | $0.003 | $0.003 | $0.003 | $0.003 |
| Supplier delivered | $0.0048 | $0.004 | $0.0036 | $0.0032 |

Worked example on Bronze: two terms across Texas, 317 suppliers = 317 × $0.004 + $0.003 = $1.271. 1,000 suppliers cost $4.003. Profile details add nothing to the price.

- Suppliers that could not be delivered are not charged. A supplier found by several searches in one run is delivered and charged once.
- The maximum total charge you set for a run is respected: with $0.031 the actor delivered exactly 7 suppliers (start fee + 7 × $0.004) and ended Succeeded, saying so (`eZjBUepLordJV8ghz`).

### Reliability and failure behaviour

| What happened | Run status | Status message (from the runs named) |
|---|---|---|
| Suppliers delivered | Succeeded | `Scraped 75 suppliers from 3 queries` (`aBQ0O9NmekVnG3Xbe`) |
| Thomasnet has no suppliers for the term | Succeeded | `0 results: Thomasnet has no suppliers for this query` (`5iw3DZmTcoLEqgdYg`) |
| State search found suppliers only outside the state | Succeeded | `0 suppliers: the 5 suppliers Thomasnet listed did not match the requested area — 5 suppliers found near … were outside … and skipped (not charged)` (offline simulation) |
| Some searches worked, some failed | Succeeded | `Scraped 6 suppliers from 3 queries — 1 of 3 queries failed ("…": Thomasnet shows this page only to signed-in users …)` (`fJDkFfGYaKBMy6No4`) |
| Nothing delivered because of blocking | **Failed** | `No suppliers delivered: Thomasnet blocked every attempt; try again later. No suppliers were charged (the start fee applies).` (offline simulation; not met live) |
| Input the actor cannot use | **Failed**, about 1 s | `"Narnia" in "states" is not a US state or Canadian province: …` (`OiVEVgPsCSE8dfAgd`); `Nothing to do: none of the 1 entries in the input is usable …` (`h7eXx73yVsOdZRJYb`) |
| Maximum charge reached | Succeeded | `Scraped 7 suppliers from 1 query — stopped at the maximum charge set for this run` (`IrTie3bDtRZmBb43D`) |
| Run timeout close | Succeeded | `Scraped 95 suppliers from 2 queries — stopped just before the run timeout; raise the timeout to get the rest` (15-second timeout, `k6mPscCiQKL1oG5he`) |

- With profile details on, a run that reaches its timeout while profiles are loading still delivers that page; the suppliers whose profile was not reached have `detailsFetched: false` (`w3fptRXC0cXI5ns2W`, 12-second timeout: 25 delivered, 10 with details).
- Thomasnet uses DataDome bot protection. Without a proxy chosen, the actor sends requests directly; as soon as one is refused it continues through Apify's US residential proxy on a fresh address per retry (up to 6 retries). In the test runs on 2026-10-20 most short searches went through directly; some runs met 1 to 5 refusals (`z51scTOrq7YfbWcUN`, `tST5NMY13L4UZRS3G`, `6CkEmYFtag6Rjajbm`, `0fq3g7GJARhSAUpqY`); each moved to residential proxy and delivered everything requested.
- Results are saved page by page. A run that is aborted, times out or is resurrected keeps what was delivered and never delivers or charges the same supplier twice. An aborted run says `Aborted by the user after 25 suppliers delivered` (`7fYfh2yMcYRcT8Rbz`).
- In all 59 test runs on 2026-10-20 and 2026-10-24 (counters re-read after the runs settled) the suppliers charged equalled the suppliers in the dataset.

### Limits

- About 25 suppliers per search (see above). A state search covers the 25 suppliers Thomasnet shows around each of the state's main cities, not every supplier in the state; cities without an entry in the list are reached through ZIP codes.
- States are US states, DC and the ten Canadian provinces. The territories (Yukon, Northwest Territories, Nunavut) are not accepted in `states` (the run fails at once with a message naming a postal area to use); put their postal areas in `zipCodes` instead, e.g. `Y1A` (Whitehorse), `X1A` (Yellowknife), `X0A` (Iqaluit). Thomasnet lists very few suppliers there ("steel" within 500 miles of Y1A: 7, all in Alaska; of X1A: 1, in Alberta; checked 2026-10-24). Radius is in miles for Canadian searches too.
- Profile details take one more page per supplier: 60 suppliers with details took 44 seconds, 317 without took 38.
- Fill rates vary by company: small companies often have no sales band, employee band or own description.

### Monitoring: only new suppliers

1. Turn on **Only new suppliers** and save the input as a task.
2. Schedule the task (weekly suits a supplier directory).
3. The first run delivers what it finds (up to the maximum). Every later run delivers and charges only suppliers not delivered before for the same search; a run with nothing new ends as Succeeded with `0 new suppliers…` and charges only the start event (`3Tum7zbNfK5UFlSWt` delivered 25, then `9CdTVRbvfqkCMH2sf` delivered 0).

The memory is a key-value store named `thomasnet-suppliers-scraper-monitor` in your own account (one record per search and monitor name, at most 10,000 ids each). Suppliers cut off by the maximum per search or by your charge limit are not marked as seen: the next run delivers (and charges) them, so with a maximum below what a search finds, later runs also deliver suppliers that were already listed but not delivered yet, not only new listings (`YSd6k8JtSMVXcXZUL` delivered 10, then `4fVfvaaScOWHgzOZZ` 10 more and `2lhngwYUcN3XZaSpZ` 5 more of the same search). Set the maximum above what a search finds if you want later runs to deliver only new listings. Changing the radius starts a new memory for that search. Delete the store or change **Monitor name** to start over.

### FAQ

**Do I need a proxy?** No. Leave it off: the actor moves to US residential proxy by itself when Thomasnet refuses a request, at no extra cost to you. Apify's datacenter proxy is refused at times (it was refused in our first probes and went through in run `QBu1LsOQobzS2UQBM`); if you choose it, the actor still switches to residential when it is refused.

**Why do I get about 25 suppliers when Thomasnet says there are thousands?** Thomasnet shows the rest only to signed-in users, and this actor does not sign in. Use ZIP codes, states or more specific terms.

**Why are certification names missing?** They are behind Thomasnet's sign-in. With profile details you get the number of certifications per type.

**Can I run it from code?** Yes: the API, the Apify clients for JavaScript and Python, Make, Zapier, n8n. The Output tab shows the URLs.

**What happens when Thomasnet changes its pages?** Runs fail loudly instead of returning empty data; report the run id under Issues.

### Legal and responsible use

This actor collects business listing data that Thomasnet shows publicly without a login: company names, company addresses, the phone numbers listed for companies, websites, company size bands and capabilities. It does not extract key personnel or other named employees, and it does not sign in or reach anything behind Thomasnet's registration wall. Company descriptions are written by Thomasnet or the company and are delivered as they are.

Thomasnet's terms of use forbid scraping and building databases from its content for third parties, and its robots.txt asks crawlers not to fetch search URLs. You are responsible for how you use the data: respect those terms, copyright and database rights, and data-protection and anti-spam law (GDPR, CAN-SPAM, Canada's CASL and PIPEDA, and others) in your country and the country of the data. Do not use the output for unsolicited marketing to individuals. If you are unsure, ask a lawyer before you build on it.

### Changelog

- 2026-10-24 0.1.15: Thomasnet's "Company Profile Section" placeholder heading is no longer listed in `allCategories` (or in `categories` of a pasted profile); records from a pasted search URL carry its search term in `searchTerm` (and its ZIP + radius in `searchLocation`) instead of `null`.

- 2026-10-24 0.1.12: `allCategories` with profile details; Canadian territories in `states` fail with a message pointing to postal areas; search terms over 200 characters are ignored; the radius is part of a state search's "only new" memory; the status message after an abort says so; default memory 256 MB.

- 2026-10-24 0.1.10: Canadian provinces in "states" (Ontario, Quebec, British Columbia, Alberta and the other six) and Canadian postal codes in "zipCodes".

- 2026-10-20 0.1.9: state searches use a smaller radius per city in small states and near state lines, and more cities in small states (DC and Rhode Island: 2 suppliers before, 62 after); "N/A"/"NONE" placeholders are null; a pasted page-2 URL fails with the sign-in message instead of returning page 1; old `what=` search URLs work; a timeout during profile details no longer drops the page.

- 2026-10-20 0.1: first version: keyword, ZIP code, state and URL searches; profile details; only-new monitoring; automatic move to residential proxy when Thomasnet refuses a request.

### Support

Open an issue on the actor's **Issues** tab with the run id.

# Actor input Schema

## `searchTerms` (type: `array`):

What the suppliers make or do, as you would type it in Thomasnet's search box, e.g. "cnc machining", "injection molding", "ball valves". One search per term (and per ZIP code or state below). Thomasnet shows visitors the first 25 suppliers of each search, in its own ranking; use ZIP codes or states to reach more. Up to 200 characters per term.

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

Optional: thomasnet.com pages to scrape as they are. A search URL (thomasnet.com/suppliers/search?searchterm=...), a category page (thomasnet.com/suppliers/usa/cnc-machining-45330503) or a company profile (thomasnet.com/company/<name>-<id>/profile). Thomasnet shows result pages after the first, and filters (company type, certification, location served), only to signed-in users: such a URL fails with a message saying so, because this actor does not sign in.

## `zipCodes` (type: `array`):

Optional: US ZIP codes (e.g. "77002") or Canadian postal codes (e.g. "M5V 2T6"; Thomasnet searches the area given by the first 3 characters, "M5V"). Each term is searched around each code within "Radius", the way Thomasnet's location box does (up to 25 suppliers per search, nearest area first in Thomasnet's ranking). Several codes with a small radius cover a metro area more completely.

## `states` (type: `array`):

Optional: US states (and DC) or Canadian provinces as code or name, e.g. "TX", "Ohio", "Washington DC", "Ontario", "QC". Canadian territories are not covered here: put their postal areas (e.g. "Y1A") in "zipCodes". Each term is searched around the state's main industrial cities (1 to 13 per state or province, within "Radius"; in small states and next to state lines a smaller radius is used per city) and only suppliers with an address in the state are kept. Coverage is the 25 suppliers Thomasnet shows per city search, so a big state yields up to a few hundred suppliers per term, not all of them. "Maximum suppliers per search" applies to each term and state together: raise it (e.g. to 300) for big states.

## `radiusMiles` (type: `integer`):

Search radius around each ZIP / postal code or state / province city, in miles. Default 50. For states, some cities use a smaller radius of their own (e.g. 5 miles in DC, 8-15 in Rhode Island and near state or national borders) so that the results stay in the state.

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

Stop each search (one term with one ZIP code, one term with one state, or one URL) after this many suppliers. A nationwide or ZIP search returns about 25 (what Thomasnet shows visitors); a state search about 25 per city, so for states raise this limit.

## `includeProfileDetails` (type: `boolean`):

Also open each supplier's Thomasnet profile and add the category headings it lists (up to 25), the company's own description, the number of certifications it lists (by type), its social media and website links, and its product families. Slower (one more page per supplier); no extra charge. Certification names and ownership/diversity status are shown only to signed-in Thomasnet users and are not included.

## `onlyNew` (type: `boolean`):

Deliver (and charge) only suppliers that earlier runs with the same searches did not deliver. The first run delivers up to the maximum and remembers what it delivered; later runs deliver suppliers not delivered before, which includes suppliers the maximum cut off earlier, not only new listings. The memory is a key-value store named thomasnet-suppliers-scraper-monitor in your account.

## `monitorKey` (type: `string`):

Optional: keeps separate "only new" memories for the same searches, e.g. one per client. Leave empty if you run one monitor.

## `proxyConfiguration` (type: `object`):

Leave off (default). Thomasnet's bot protection refuses some requests, from data-center addresses more often; when it refuses one, the actor continues through Apify's US residential proxy on its own. Set a proxy here only to force every request through it from the start.

## Actor input object example

```json
{
  "searchTerms": [
    "cnc machining"
  ],
  "radiusMiles": 50,
  "maxItems": 10,
  "includeProfileDetails": false,
  "onlyNew": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All delivered suppliers as JSON, one object per supplier. Main fields: id, name, supplierType, additionalActivities, description, street, city, state, postalCode, country, latitude, longitude, phone, website, annualSales, employees, yearFounded, categories, matchedCategory, materials, industries, productionScale, catalogItems, distanceMiles, thomasTier, isAdvertiser, isClaimed, profileUrl, profile details (companyDescription, certificationCount, socialLinks, productFamilies) when requested, searchTerm, searchLocation, searchRank, scrapedAt. A value the source does not give is null.

## `resultsCsv` (type: `string`):

All delivered suppliers as a CSV file, one row per supplier, with the same fields as the JSON output (lists are flattened into columns).

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

JSON record OUTPUT_SUMMARY: what was requested, delivered and charged; per search how many suppliers Thomasnet reports against how many it shows; which inputs failed or were ignored and why; whether the run moved to residential proxy; why the run stopped.

# 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 = {
    "searchTerms": [
        "cnc machining"
    ],
    "maxItems": 10,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("amitaviv/thomasnet-suppliers-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 = {
    "searchTerms": ["cnc machining"],
    "maxItems": 10,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("amitaviv/thomasnet-suppliers-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 '{
  "searchTerms": [
    "cnc machining"
  ],
  "maxItems": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call amitaviv/thomasnet-suppliers-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,amitaviv/thomasnet-suppliers-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/oQrPlStt7KjbQAmtI/builds/O97NasvBduVZ9Ru2a/openapi.json
