OpenCorporates APIopencorporates.com ↗
Access company registration details, officer records, and filing histories across global jurisdictions via the OpenCorporates API. 6 endpoints.
What is the OpenCorporates API?
This API exposes 6 endpoints for querying OpenCorporates data, covering company registration records, officer details, filing histories, and jurisdiction listings across hundreds of global jurisdictions. Use search_companies to find companies by name with filters for jurisdiction, company type, and status, or call get_company to retrieve the full registration record for a known company number.
curl -X GET 'https://api.parse.bot/scraper/094dd742-46a2-442e-8d2b-a99f7200f14d/search_companies' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace opencorporates-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""
OpenCorporates API & Scraper Client
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from typing import Optional, Dict, Any, List
class ParseClient:
"""Client for interacting with OpenCorporates data through Parse API."""
def __init__(self, api_key: Optional[str] = None):
"""Initialize the Parse client.
Args:
api_key: OpenCorporates API token. If not provided, will use PARSE_API_KEY env var.
"""
self.base_url = "https://api.parse.bot"
self.scraper_id = "e95ef62d-606c-418a-ae4e-3133289dc899"
self.api_key = api_key or os.getenv("PARSE_API_KEY")
if not self.api_key:
raise ValueError("API key must be provided or set in PARSE_API_KEY environment variable")
def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
"""Make a request to the Parse API.
Args:
endpoint: The endpoint name (e.g., 'search_companies')
method: HTTP method ('GET' or 'POST')
**params: Parameters to pass to the endpoint
Returns:
Response JSON as dictionary
"""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
if method.upper() == "GET":
response = requests.get(url, headers=headers, params=params)
elif method.upper() == "POST":
response = requests.post(url, headers=headers, json=params)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
return response.json()
def search_companies(
self,
query: str,
api_token: Optional[str] = None,
country_code: Optional[str] = None,
jurisdiction_code: Optional[str] = None,
company_type: Optional[str] = None,
current_status: Optional[str] = None,
page: int = 1
) -> Dict[str, Any]:
"""Search for companies by name across all or a specific jurisdiction.
Args:
query: Search keyword (company name)
api_token: OpenCorporates API token
country_code: Filter by country code
jurisdiction_code: Filter by jurisdiction code (e.g., us_de)
company_type: Filter by company type
current_status: Filter by current status (e.g., Active)
page: Page number for pagination
Returns:
Dictionary with 'companies' array and 'total_count'
"""
params = {"query": query, "page": page}
if api_token:
params["api_token"] = api_token
if country_code:
params["country_code"] = country_code
if jurisdiction_code:
params["jurisdiction_code"] = jurisdiction_code
if company_type:
params["company_type"] = company_type
if current_status:
params["current_status"] = current_status
return self._call("search_companies", method="GET", **params)
def get_company(
self,
jurisdiction_code: str,
company_number: str,
api_token: Optional[str] = None,
sparse: bool = False
) -> Dict[str, Any]:
"""Retrieve full details for a specific company.
Args:
jurisdiction_code: Jurisdiction code (e.g., us_de)
company_number: Company registration number
api_token: OpenCorporates API token
sparse: Return lightweight response if True
Returns:
Dictionary with company details
"""
params = {
"jurisdiction_code": jurisdiction_code,
"company_number": company_number,
"sparse": str(sparse).lower()
}
if api_token:
params["api_token"] = api_token
return self._call("get_company", method="GET", **params)
def scrape_company_page(
self,
jurisdiction_code: str,
company_number: str
) -> Dict[str, Any]:
"""Scrape OpenCorporates HTML company page for registration details, officers, and filings.
Args:
jurisdiction_code: Jurisdiction code (e.g., us_de)
company_number: Company registration number
Returns:
Dictionary with company_name, officers, filings, attributes, and url
"""
params = {
"jurisdiction_code": jurisdiction_code,
"company_number": company_number
}
return self._call("scrape_company_page", method="GET", **params)
def scrape_officer_page(self, officer_id: str) -> Dict[str, Any]:
"""Scrape OpenCorporates HTML officer page for details and associated companies.
Args:
officer_id: OpenCorporates officer ID
Returns:
Dictionary with officer_name, attributes, companies, and url
"""
params = {"id": officer_id}
return self._call("scrape_officer_page", method="GET", **params)
def search_officers(
self,
query: str,
api_token: Optional[str] = None,
page: int = 1
) -> Dict[str, Any]:
"""Search for company officers by name.
Args:
query: Officer name search keyword
api_token: OpenCorporates API token
page: Page number for pagination
Returns:
Dictionary with 'officers' array and 'total_count'
"""
params = {"query": query, "page": page}
if api_token:
params["api_token"] = api_token
return self._call("search_officers", method="GET", **params)
def list_jurisdictions(self, api_token: Optional[str] = None) -> Dict[str, Any]:
"""List all jurisdictions supported by OpenCorporates.
Args:
api_token: OpenCorporates API token
Returns:
Dictionary with 'jurisdictions' array
"""
params = {}
if api_token:
params["api_token"] = api_token
return self._call("list_jurisdictions", method="GET", **params)
def main():
"""Practical workflow example: Research companies and their officers."""
# Initialize the client
client = ParseClient()
# Step 1: Search for companies by name
print("=" * 60)
print("STEP 1: Searching for companies named 'Cribl'...")
print("=" * 60)
search_results = client.search_companies(
query="Cribl",
jurisdiction_code="us_de",
current_status="Active"
)
print(f"Found {search_results['total_count']} company(ies)")
if search_results['companies']:
# Step 2: Get details for the first company found
first_company = search_results['companies'][0]['company']
jurisdiction = first_company['jurisdiction_code']
company_number = first_company['company_number']
company_name = first_company['name']
print(f"\nSelected company: {company_name} ({jurisdiction}/{company_number})")
# Step 3: Scrape the company page for detailed information
print("\n" + "=" * 60)
print("STEP 2: Scraping company page for officers and filings...")
print("=" * 60)
company_page = client.scrape_company_page(
jurisdiction_code=jurisdiction,
company_number=company_number
)
print(f"Company: {company_page.get('company_name')}")
print(f"URL: {company_page.get('url')}")
# Display company attributes
if company_page.get('attributes'):
print("\nCompany Attributes:")
for key, value in company_page['attributes'].items():
print(f" {key}: {value}")
# Step 4: Process officers
if company_page.get('officers'):
print(f"\nOfficers ({len(company_page['officers'])}):")
for officer in company_page['officers']:
print(f" - {officer.get('name', 'Unknown')} ({officer.get('role', 'Unknown role')})")
# Step 5: Display filings
if company_page.get('filings'):
print(f"\nRecent Filings ({len(company_page['filings'])}):")
for filing in company_page['filings'][:5]: # Show first 5
print(f" - {filing.get('title', 'Unknown')} ({filing.get('date', 'Unknown date')})")
# Step 6: Search for officers with the same name
print("\n" + "=" * 60)
print("STEP 3: Searching for officers with similar names...")
print("=" * 60)
if company_page.get('officers'):
first_officer_name = company_page['officers'][0].get('name')
if first_officer_name:
officer_search = client.search_officers(query=first_officer_name)
print(f"Found {officer_search.get('total_count', 0)} officer(s) named '{first_officer_name}'")
if officer_search.get('officers'):
print(f"\nFirst officer result: {officer_search['officers'][0]['officer']['name']}")
print("\n" + "=" * 60)
print("Workflow completed successfully!")
print("=" * 60)
if __name__ == "__main__":
main()Search for companies by name across all or a specific jurisdiction. Requires API token.
| Param | Type | Description |
|---|---|---|
| page | integer | Page number for pagination |
| queryrequired | string | Search keyword (company name) |
| api_token | string | OpenCorporates API token |
| company_type | string | Filter by company type |
| country_code | string | Filter by country code |
| current_status | string | Filter by current status (e.g., Active) |
| jurisdiction_code | string | Filter by jurisdiction code (e.g., us_de) |
{
"type": "object",
"fields": {
"companies": "array of objects",
"total_count": "integer"
},
"sample": {
"companies": [
{
"company": {
"name": "Cribl, Inc.",
"company_number": "7371712",
"jurisdiction_code": "us_de"
}
}
],
"total_count": 1
}
}About the OpenCorporates API
Company Search and Lookup
The search_companies endpoint accepts a query string and returns an array of matching companies along with a total_count integer. You can narrow results using jurisdiction_code (e.g., us_de for Delaware), country_code, company_type, and current_status. Pagination is handled with the page parameter. The get_company endpoint fetches a single company record by jurisdiction_code and company_number, returning a company object with full registration details. Pass sparse=true for a lighter payload when only basic fields are needed.
Officer Search and Profiles
search_officers queries officer records by name and returns an officers array with a total_count. Each result includes the officer's association with one or more companies. The scrape_officer_page endpoint takes an OpenCorporates id and returns officer_name, an attributes object of key-value metadata, and a companies array listing every corporate involvement recorded for that individual.
Filing History and Registration Attributes
scrape_company_page returns structured data from the full company profile: company_name, an attributes object containing registration metadata (such as incorporation date, registered address, and company type), an officers array, and a filings array with historical filing records. This endpoint does not require an API token but may encounter hCaptcha challenges on some requests.
Jurisdiction Coverage
The list_jurisdictions endpoint returns a jurisdictions array describing every jurisdiction OpenCorporates indexes. OpenCorporates covers company registries from over 140 jurisdictions worldwide, making it one of the broader sources for cross-border corporate data. All token-required endpoints expect an api_token parameter tied to an OpenCorporates account.
The OpenCorporates API is a managed, monitored endpoint for opencorporates.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when opencorporates.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official opencorporates.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Due diligence: retrieve full company registration details and filing history for a target entity by jurisdiction and company number.
- Officer background checks: search officers by name and pull all associated corporate involvements via scrape_officer_page.
- Corporate network mapping: link officers to multiple companies using the companies array returned by the officer endpoints.
- Compliance screening: filter company searches by current_status to identify active versus dissolved entities in a specific jurisdiction.
- Jurisdiction enumeration: use list_jurisdictions to determine which registries are indexed before programmatically searching across multiple regions.
- Registered agent research: extract attributes from scrape_company_page to surface registered address and agent details from historical filings.
- Bulk corporate data enrichment: paginate search_companies results to build datasets of companies matching a type or status within a country.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does OpenCorporates have an official developer API?+
search_companies, get_company, search_officers, list_jurisdictions) pass through to that official API.What does the scrape_company_page endpoint return that get_company does not?+
scrape_company_page endpoint returns a filings array with historical filing records and an officers array alongside the attributes object — detail that may not be fully present in the official API's get_company response depending on the jurisdiction and your API tier. It does not require an API token but may encounter hCaptcha on some requests.Can I retrieve beneficial ownership or shareholder data?+
How does pagination work across the search endpoints?+
search_companies and search_officers accept an integer page parameter. The response includes a total_count so you can calculate how many pages exist at the default page size. There is no cursor-based pagination; increment page numerically to walk through results.