When querying corporate registries via an automated pipeline, engineers typically expect an exact-match query pattern: a search for a non-existent company name returns an empty array. The Florida Division of Corporations registry (Sunbiz) does not follow this model.
Sunbiz treats entity name, registered agent, officer, FEI/EIN, ZIP code, and street address queries as pointers into an alphabetically or numerically sorted index. If you query an entity name that does not exist, the search portal does not yield an empty result; instead, it starts browsing from the nearest alphabetical neighbor and returns the next records in line. Understanding how to handle this index structure is critical when building verification, compliance, or lead generation ingestion pipelines.
Understanding Sunbiz Index Traversal
Sunbiz exposes multiple search axes, but their matching mechanics differ depending on the underlying data type:
-
Exact-Match Key:
documentNumberis the only search axis acting as a strict primary key. A query on an invalid or unassigned document number returns a "Document Not Found" message rather than surrounding entries. -
Alphabetical and Numerical Index Browsing: All other search types (
entityName,officerOrRegisteredAgent,registeredAgentName,feiEinNumber,zipCode,address,trademarkName, andtrademarkOwnerName) perform a "starts-with" or nearest-position lookup. If an exact match does not exist, the index returns the adjacent records.
Additionally, searching by zipCode or address indexes across principal, mailing, and registered-agent addresses simultaneously. A match on any of those three fields causes an entity to appear in the results, which often surprises developers expecting only principal address matches. Furthermore, Sunbiz shares its name-based indexes with trademark records, meaning a name search can return records where entityType is Trademark alongside standard corporate filings.
Automating these extractions requires an ingestion tool that parses detail pages for each entity while managing pagination across Sunbiz's 20-record-per-page lists.
Automated Extraction with the Sunbiz Scraper
The Florida Sunbiz Business Entity Search Scraper handles the search traversal, pagination, and detail-page enrichment over direct HTTP. It pulls full entity records, extracts corporate officers, normalizes status values, and resolves direct PDF links to filed documents when the document-image server is reachable.
Core Input Schema
The scraper accepts several input parameters to control index execution:
-
searchType(string, required): Specifies the search axis (entityName,officerOrRegisteredAgent,registeredAgentName,feiEinNumber,documentNumber,zipCode,address,trademarkName,trademarkOwnerName). -
searchTerm(string, required): The target string, number, or address. -
entityStatus(string): Pre-filters records on the detail page level to emit onlyactive,inactive, oranystatuses. -
maxItems(integer): Sets a hard cap between 1 and 200 emitted records, automatically walking Sunbiz's "Next List" pagination buttons to fulfill counts above 20. -
proxyConfiguration(object): Configures automatic fallback proxies if direct datacenter requests are throttled.
Output Structure
Each emitted item from a business entity search normalizes the scraped detail page into standard properties. Sunbiz omits empty fields if the state filing lacks them:
{
"entityName": "PUBLIX SUPER MARKETS, INC.",
"entityType": "Florida Profit Corporation",
"documentNumber": "112252",
"feiEinNumber": "590324412",
"filingDate": "09/29/1921",
"state": "FL",
"status": "ACTIVE",
"principalAddress": "3300 PUBLIX CORPORATE PARKWAY, LAKELAND, FL 33811",
"mailingAddress": "P.O. BOX 407, LAKELAND, FL 33802",
"registeredAgentName": "CORPORATION SERVICE COMPANY",
"registeredAgentAddress": "1201 HAYS STREET, TALLAHASSEE, FL 32301",
"officers": [
{
"title": "CEO",
"name": "JONES, KEVIN M",
"address": "3300 PUBLIX CORPORATE PARKWAY, LAKELAND, FL 33811"
}
],
"annualReports": [
{
"year": "2024",
"filedDate": "01/15/2024"
}
],
"filedDocuments": [
{
"label": "01/15/2024 -- ANNUAL REPORT",
"pdfUrl": "http://search.sunbiz.org/Inquiry/CorporationSearch/GetDocument?..."
}
],
"sourceUrl": "http://search.sunbiz.org/Inquiry/CorporationSearch/SearchResultDetail?...",
"searchType": "entityName",
"searchTerm": "publix super markets",
"recordType": "businessEntity",
"scrapedAt": "2024-03-20T14:32:10.123Z"
}
Running an Extraction Pipeline
You can configure and trigger runs programmatically via the Apify Python SDK or standard REST endpoints.
Step 1: Define the Input Payload
To query active entities within a target ZIP code and limit results to the first 40 records:
{
"searchType": "zipCode",
"searchTerm": "33811",
"entityStatus": "active",
"maxItems": 40
}
Step 2: Execute the Actor via Python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run_input = {
"searchType": "entityName",
"searchTerm": "florida logistics llc",
"entityStatus": "active",
"maxItems": 20,
}
# Run the actor and wait for completion
run = client.actor("crawlerbros/florida-sunbiz-business-entity-search-scraper").call(
run_input=run_input
)
# Fetch dataset items
dataset_items = client.dataset(run["defaultDatasetId"]).list_items().items
for item in dataset_items:
print(f"Entity: {item.get('entityName')} | Status: {item.get('status')}")
for officer in item.get("officers", []):
print(f" - Officer: {officer.get('name')} ({officer.get('title')})")
Step 3: Handle Post-Extraction Name Verification
Because of Sunbiz's index browsing mechanics, if "florida logistics llc" is not an exact match, the scraper emits the nearest alphabetical entities following that point in the index. Downstream code should compare the returned entityName against the input searchTerm to distinguish between exact matches and neighbor records:
def verify_exact_match(scraped_item, original_query):
query_norm = original_query.strip().upper()
entity_norm = scraped_item.get("entityName", "").strip().upper()
return query_norm == entity_norm
Pricing and Cost Modeling
The scraper operates strictly on a pay-per-event pricing model. Charges are calculated entirely on two flat event types:
-
Actor Start (
apify-actor-start): $0.005 per GB of memory allocated to the run, charged once when the run begins. -
Result (
apify-default-dataset-item): Billed per dataset record emitted. The standard pricing tier is $0.005 per result on the FREE tier, with volume tiers offering $0.00433 (BRONZE), $0.00367 (SILVER), and $0.003 (GOLD, PLATINUM, DIAMOND).
A run extracting 100 entities on 1 GB of memory on the standard tier costs $0.005 for the start event plus $0.50 for the 100 result events ($0.005 × 100), totaling $0.505.
Tool Limitations
This tool does not parse owner details from trademark filings into structured officer objects; when a query matches a trademark, owner data remains unparsed because trademark detail records on Sunbiz omit standard officer and registered agent tables. Pipelines requiring structured trademark owner entities will need supplementary parsing logic for those specific records.
Florida Sunbiz Business Entity Search Scraper is what these steps drive. The README covers the inputs this article skipped, including the ones that change how much a run costs.
Top comments (0)