FCC ULS License Scraper - Business Radio & Microwave Licenses avatar

FCC ULS License Scraper - Business Radio & Microwave Licenses

Pricing

from $2.10 / 1,000 licenses

Go to Apify Store
FCC ULS License Scraper - Business Radio & Microwave Licenses

FCC ULS License Scraper - Business Radio & Microwave Licenses

Scrape FCC Universal Licensing System (ULS) business/industrial land-mobile radio (IG, YG) and point-to-point microwave (CF, MG) licenses by state, status, and expiration window from FCC bulk files.

Pricing

from $2.10 / 1,000 licenses

Rating

0.0

(0)

Developer

Groundplane Labs

Groundplane Labs

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Scrape commercial land-mobile business radio (IG, YG, GJ, YO, YB, YI, etc.) and point-to-point microwave (CF, MG, NN, TP, etc.) licenses directly from the Federal Communications Commission (FCC) Universal Licensing System (ULS) weekly bulk license archives (l_LMpriv.zip and l_micro.zip). Filter by radio service code, licensee state, license status, or upcoming expiration window to identify organizations operating commercial radio and microwave infrastructure.

Disclaimer: This Actor is an independent tool and is not affiliated with or endorsed by the Federal Communications Commission (FCC).


What it does

  • Streams FCC ULS Bulk Archives via HTTP Range Requests: Queries the official FCC ULS complete license archives (l_LMpriv.zip and l_micro.zip on data.fcc.gov) using ZIP Central Directory HTTP Range requests to stream and decompress only the License Header (HD.dat) and Entity (EN.dat) tables.
  • Commercial Business Radio & Microwave Coverage: Supports Private Land Mobile Industrial/Business Pool (IG, YG, YB, YI, YO, GJ, GO, etc.) and Microwave (CF, MG, NN, TP, etc.) radio service codes.
  • Expiring License Detection: In EXPIRING mode, filters active (A) licenses expiring between today and today + expiringWithinDays (default 180 days) and calculates exact daysUntilExpiration.
  • Privacy Controls Built In: Individual licensees are excluded by default: any row with applicant_type_code == 'I' is individual unconditionally, a row whose entity name is in LAST, FIRST form built from its last/first name fields is individual, a row with a personal first/last name and no business entity name is individual, and a partnership (applicant_type_code == 'P') row whose entity name has no business marker (such as LLC, LP, LLP, INC, CO, or CORP) is filtered the same way. Contact fields (contactName, contactEmail, contactPhone) are also excluded by default (includeIndividualLicensees: false, includeContacts: false).
  • Actionable Ordering: In EXPIRING mode, results are sorted by expirationDate ascending (soonest expiring first) so urgent renewals appear first; in all other modes (ACTIVE, EXPIRED, CANCELLED), results are sorted by grantDate descending (newest first) before applying maxItems.

Who it's for

  • Two-Way Radio & Land Mobile Dealers: Find commercial facilities, farms, warehouses, construction firms, hotels, utilities, and school districts whose FCC Part 90 business radio (IG / YG) licenses are approaching their 10-year renewal window.
  • Telecom & Backhaul Providers: Track common carrier (CF) and private operational fixed (MG) point-to-point microwave links by state and expiration date.
  • FCC Licensing & Compliance Consultants: Monitor upcoming license expirations and recently cancelled or expired licenses requiring renewal or re-coordination.
  • Infrastructure & M&A Analysts: Audit active spectrum holdings and wireless infrastructure footprints across corporate entities (by FRN and call sign).

Input

All parameters have working defaults/prefills that return results in under 2 minutes.

FieldTypeDefault / PrefillDescription
radioServiceCodesarray<string>["IG", "YG"]FCC ULS radio service codes. Land Mobile uses l_LMpriv.zip (IG, YG, YB, YI, YO, GJ, GO, etc.); Microwave uses l_micro.zip (CF, MG, NN, TP, etc.).
statesarray<string>["AZ"]Two-letter US state or territory postal codes for the licensee address (e.g. ["AZ"], ["AZ", "NV"]). Leave empty for all states.
statusstring"EXPIRING"EXPIRING (Active licenses expiring within expiringWithinDays), ACTIVE, EXPIRED, or CANCELLED (includes Cancelled C and Terminated T).
expiringWithinDaysinteger180Lookahead window in days when status is "EXPIRING".
includeContactsbooleanfalseInclude a named attention contact, email, and telephone number (contactName, contactEmail, contactPhone) from EN.dat. Defaults to false for privacy compliance.
includeIndividualLicenseesbooleanfalseInclude licenses held by natural persons. A licensee is a natural person when applicant_type_code == 'I' (unconditionally), when EN.dat has a first/last name and no business entity name, or when the entity name is in LAST, FIRST form. Partnership rows (applicant_type_code == 'P') with no business marker in the entity name are treated the same way. Defaults to false so only organizational/business licensees are returned.
maxItemsinteger200Maximum number of license records to output.

Example input JSON

{
"radioServiceCodes": ["IG", "YG"],
"states": ["AZ"],
"status": "EXPIRING",
"expiringWithinDays": 180,
"includeContacts": false,
"includeIndividualLicensees": false,
"maxItems": 200
}

Example run options (with default $50 max charge protection)

When invoking via the Apify API or CLI, set a default maximum charge of $50 ("maxTotalChargeUsd": 50):

{
"maxTotalChargeUsd": 50
}

The Actor checks calculate_max_event_charge_count_within_limit("apify-default-dataset-item") before every dataset push and stops cleanly when your spending limit is reached.


Output

Results are saved to the default dataset. Deduplication is enforced by callSign + uniqueSystemId.

Output fields

FieldTypeDescription
callSignstringFCC license call sign (HD.dat column 5).
uniqueSystemIdstringFCC ULS unique_system_identifier (HD.dat column 2).
frnstring | null10-digit FCC Registration Number (FRN).
licenseeNamestring | nullBusiness or institutional licensee name (EN.dat entity name).
radioServicestring2-letter FCC radio service code (e.g. IG, YG, CF, MG).
licenseStatusstringNormalized status: Active, Expired, Cancelled, or Terminated.
grantDatestring | nullLicense grant date in YYYY-MM-DD format.
expirationDatestring | nullLicense expiration date in YYYY-MM-DD format.
daysUntilExpirationinteger | nullCalendar days from today (UTC) until expirationDate (negative if already expired).
streetstring | nullLicensee street address or P.O. Box.
citystring | nullLicensee city.
statestring | nullTwo-letter state or territory code.
zipstring | nullLicensee postal ZIP code (formatted XXXXX or XXXXX-XXXX).
ulsUrlstringDirect link to the FCC ULS license page (https://wireless2.fcc.gov/UlsApp/UlsSearch/license.jsp?licKey=<uniqueSystemId>).
contactNamestring | nullIncluded only when includeContacts is true.
contactEmailstring | nullIncluded only when includeContacts is true.
contactPhonestring | nullIncluded only when includeContacts is true.

Sample output row (synthetic example)

{
"callSign": "WQXM901",
"uniqueSystemId": "3891042",
"frn": "0025918402",
"licenseeName": "DESERT RIDGE LOGISTICS LLC",
"radioService": "IG",
"licenseStatus": "Active",
"grantDate": "2016-11-18",
"expirationDate": "2026-11-18",
"daysUntilExpiration": 18,
"street": "4200 W BUCKEYE RD",
"city": "PHOENIX",
"state": "AZ",
"zip": "85009",
"ulsUrl": "https://wireless2.fcc.gov/UlsApp/UlsSearch/license.jsp?licKey=3891042"
}

(If includeContacts: true is enabled, optional contact fields "contactName": "FLEET OPERATIONS DEPT", "contactEmail": "radio-compliance@example.com", and "contactPhone": "602-555-0199" are also included.)


How pricing works

Pay per result. You only pay for rows returned.


Data source and terms

  • Official Source: Federal Communications Commission (FCC) — Universal Licensing System (ULS) Public Access Files / Database Downloads
  • Bulk Archive Endpoints:
    • Private Land Mobile (l_LMpriv.zip): https://data.fcc.gov/download/pub/uls/complete/l_LMpriv.zip
    • Microwave (l_micro.zip): https://data.fcc.gov/download/pub/uls/complete/l_micro.zip
  • Update Cadence: Complete license archives are generated weekly (typically Sunday morning) by the FCC.
  • Terms of Use: FCC ULS public access files are U.S. Government public records published under FCC Privacy & Data Policy.

Compliance

This Actor retrieves public licensing records published by the Federal Communications Commission (FCC). Personal contact fields (includeContacts and includeIndividualLicensees) are turned off by default.

If you enable contact fields or use organization address data for outreach:

  • Regulatory Compliance: Buyers are solely responsible for complying with the Telephone Consumer Protection Act (TCPA), the National Do-Not-Call (DNC) Registry, the CAN-SPAM Act, and all applicable state and international privacy and telemarketing laws before conducting any outreach.
  • No Consumer / Individual Targeting: This tool is designed for B2B commercial infrastructure research (e.g., corporate, industrial, utility, and institutional radio licensees) and must not be used for consumer or individual targeting.

Limits and FAQ

  • Why does the Actor use 1 GB memory (1024 MB)? The FCC's complete Land Mobile Private archive (l_LMpriv.zip) is ~424 MB compressed (~2.5 GB uncompressed across all tables). This Actor uses HTTP Range requests against the ZIP Central Directory to stream and decompress only HD.dat (~26.7 MB compressed) and EN.dat (~75.3 MB compressed) in 256 KB chunks, filtering rows in memory in ~14 seconds. If a network intermediary ignores Range requests, the Actor downloads the full archive once and extracts the same two tables locally rather than misreading offsets. Measured peak memory on the worst case (all states, ACTIVE, IG+YG+CF+MG) is about 616 MB, so 1024 MB is enough even when querying multiple states and both Land Mobile and Microwave archives in a single run.
  • Why does the Actor keep the stock python-httpx User-Agent? Documented exception: data.fcc.gov is Akamai-fronted. Retested 2026-11-01 via httpx, the identified neutral UA GroundplaneLabs-Apify/1.0 (no email) passes GET Range requests (206) but fails HEAD requests (403 on every trial), and this Actor relies on HEAD to inspect each archive. The stock library UA passes both HEAD (200) and GET Range (206) and does not impersonate a browser, so it is kept deliberately.
  • What happens when 0 rows match? Zero matches on a healthy source is a successful run: the status reads Complete: 0 licenses matched your filters and states how many records were scanned, plus which filters (states, expiringWithinDays, status, or radioServiceCodes) to widen. A run only fails loudly when the source itself is broken (empty or restructured files, failed downloads), so upstream data changes never fail silently.
  • Can I query both Land Mobile (IG, YG) and Microwave (CF, MG) in one run? Yes. The Actor automatically maps each requested radio service code to l_LMpriv.zip or l_micro.zip and downloads only the required archive(s).

Troubleshooting

  • Canary input: to smoke-test the Actor, run the default input above with "maxItems": 5. It returns rows in well under a minute on a healthy source and ends with a Complete: status.
  • Status starts with PARTIAL:: the run finished but something material was withheld, and the status message says exactly why (for example a stale weekly archive, a failed source archive, or rows skipped by validation). Rows already collected are still delivered.
  • Status starts with Complete: 0 licenses matched: the source is healthy and records were scanned, but no license fits your filters. Widen expiringWithinDays, add states or radioServiceCodes, or switch status to ACTIVE.
  • Run failed with a layout or download message: the FCC changed or failed to publish a bulk file. Retry once; if it persists, report it as below.

Found a problem or need a field? Open an issue on the Issues tab; we respond quickly.


Changelog

v0.1.3 (2026-11-01)

  • Privacy fix (Blocker): applicant_type_code == 'I' rows are now individual unconditionally, entity names in LAST, FIRST form are treated as individual, and partnership (P) rows with no business marker in the entity name are filtered by default. Added a unit test for the individual test.
  • Retry policy aligned to the fleet standard: 6 tries, jittered backoff from 2 to 32 seconds capped at 120 seconds, with Retry-After honored as seconds or as an HTTP date.
  • Default memory reduced from 4096 MB to 1024 MB (measured worst case about 616 MB). Strict boolean parsing for includeContacts and includeIndividualLicensees. Non-US state codes are pre-filtered and counted as filtered instead of failing validation. Listing wording uses singular contact naming and the description starts with "Scrape". User-Agent: the identified neutral UA was retested via httpx and fails HEAD, so the stock UA is kept as a documented exception (see Limits and FAQ).

v0.1.2 (2026-10-31)

  • Red Team fix round (download integrity): the ZIP central-directory CRC32 is now carried through the download path; every 206 response has its Content-Range verified against the requested range; and decompression verifies the end-of-stream marker, the decompressed byte count, and the CRC32 against the central directory, so a truncated or corrupted stream fails loudly instead of yielding a partial table.

v0.1.1 (2026-10-31)

  • Fixed run status contract: runs now end with Complete: or PARTIAL: with honest scanned / matched / emitted counts; zero matches on a healthy source is a Complete: 0 success instead of a failure.
  • Added per-row output validation before push and a core-column sentinel on HD.dat / EN.dat that fails loudly if the FCC restructures the files.
  • Added per-archive isolation (one failed archive no longer discards the other's rows), a staleness check on the weekly archives, and a full-download fallback when a network intermediary ignores HTTP Range requests.
  • Store categories corrected to Business only; default run options now include the $50 max charge; an explicit empty states list now means all states, as documented.

v0.1 (2026-10-31)

  • Initial release supporting FCC ULS Land Mobile Private (l_LMpriv.zip) and Microwave (l_micro.zip) bulk archives via HTTP Range streaming.
  • Added EXPIRING, ACTIVE, EXPIRED, and CANCELLED filtering, state filtering, and privacy-first contact flags (includeContacts, includeIndividualLicensees default false).