FilingWire
Get an API key
Guide

How to map a ticker to a CIK

EDGAR is keyed on CIK, and nothing in it is keyed on ticker. The map is one public file, and the mistake is treating the relationship as one to one.

01

CIK is the identifier that lasts

The Central Index Key is assigned by SEC and does not change. A ticker changes: companies re-list, rebrand, move exchange and get acquired, and the symbol gets reused by somebody else afterwards. Anything you store keyed on ticker is storing a value with an expiry date on it.

So resolve ticker to CIK at the edge, and key everything behind that on the CIK. That is how EDGAR itself is organised and it is not worth fighting.

02

The map is one file

SEC publishes company_tickers.json, which is small enough to fetch and hold in memory. It is a dict keyed by an index rather than a list, and the CIK inside it is an integer, so zero-pad it to the ten-digit form everything else uses.

There is a companion file carrying the exchange for each symbol. It is an overlay, not a replacement: it lists slightly fewer symbols, so treat a symbol missing from it as "no exchange recorded" rather than as not existing.

ticker -> CIK
import requests

HEADERS = {"User-Agent": "Example Research (hello@example.com)"}


def ticker_to_cik() -> dict:
    """Every symbol SEC publishes, mapped to a zero-padded CIK.

    Build it this way round and store the CIK. One company can carry several
    symbols, so the relation is many-to-one, and the ticker is the side that
    changes.
    """
    payload = requests.get(
        "https://www.sec.gov/files/company_tickers.json",
        headers=HEADERS, timeout=30,
    ).json()
    # A dict keyed by an index: {"0": {"cik_str": 320193, "ticker": "AAPL", ...}}
    return {
        str(row["ticker"]).upper(): str(row["cik_str"]).zfill(10)
        for row in payload.values()
        if row.get("ticker")
    }
03

One company, several symbols

The relation is many-to-one. Share classes are the common case, and a single CIK can carry several tickers on one or more venues. If your schema has a ticker column on the company, you have already lost one of them.

Store the symbols as a list joined to the CIK, and return a list. Our own 8-K table carries no ticker column for exactly this reason: the symbols are joined per request from the map, which also means a re-listing does not require rewriting history.

04

Where ticker stops being useful

For private-market filings it barely applies. Form D issuers are mostly private companies, and on a sample of our own issuer table taken on 2026-07-26 fewer than one in twenty carried a symbol. A ticker field on that data would be empty nineteen times in twenty, which is worse than not having one because it looks like a gap in the data rather than a property of the universe.

A ticker that resolves also does not imply there is anything to find. A large, well-known symbol maps to a real CIK and can still have filed no material 8-K in the window you are looking at. Those are different answers and worth reporting differently.

Common questions

Where can I download a ticker to CIK mapping?

SEC publishes company_tickers.json on sec.gov, free and without a key. A companion file adds the listing exchange for most symbols. Both are small enough to fetch on a schedule and cache.

Can one company have more than one ticker?

Yes, commonly, through multiple share classes. The relation is many-to-one against CIK, so store a list rather than a single column, or you will silently drop share classes.

Do private companies have a ticker?

Almost never, which makes ticker the wrong lookup key for Form D data. CIK is assigned to every filer, public or private, and is the only identifier that works across both.

Or do not maintain it

Everything above is real work, and it does not stop.

The parsing is the easy half. The rest is the daily pass, the rescan window, the filings that arrive backdated and the ones that never produce a row. We run it and serve the result as JSON, and the free key needs no card. If you would rather own the pipeline, the code above is what we would write.

Try a live query