Which tool to reach for

You wantUse
To look up or search anatomic locations in Python, or from a shellThe anatomic-locations package and its CLI
The same from TypeScript or JavaScript@talkasab/body_part_index, against the older dataset
The raw data, no dependencyThe JSON download from the project site
To curate the set itselfThe manage-anatomic-locations skill in findingmodel, and laterality conventions

Installation and configuration detail belongs with the code and is not repeated here. The package README and the anatomic locations guide in findingmodel are the reference.12

The anatomic-locations package

pip install anatomic-locations. The database downloads automatically on first use and there is no setup step.1 Lookup accepts a RadLex identifier, a description, or a synonym, all case-insensitive.

from anatomic_locations import AnatomicLocationIndex
 
index = AnatomicLocationIndex()
location = index.get("RID2772")   # by identifier
location = index.get("kidney")    # by description
location = index.get("renal")     # by synonym
print(location.description)       # "kidney"
print(location.region.value)      # "Abdomen"

Four capabilities matter in practice.

Direct lookup and code lookup. get() for the three forms above, and find_by_code(system, code) to come in from SNOMED CT, FMA, or RadLex. The assignment rules for the extraction platform tell coders to prefer direct lookup over search for a named target organ, because search is less reliable and produces retrieval misses such as “prostate” returning salivary glands.3

Hierarchy traversal. get_containment_ancestors() and get_containment_descendants() on a location, plus get_children_of() on the index. Both the containment and the part-of hierarchies are backed by materialized paths, so these are not recursive queries.

Laterality variants. get_laterality_variants() returns a mapping from a Laterality member to the corresponding location, so a generic structure yields its left and right records.

lymph_node = index.get("RID1517")
variants = lymph_node.get_laterality_variants()
# Laterality.LEFT  -> RID1517_RID5824, left axillary lymph node
# Laterality.RIGHT -> RID1517_RID5825, right axillary lymph node

Hybrid search. search() and search_batch() are async and combine full-text search with vector search over embeddings. Semantic search turns on when an OpenAI key is present; without one, search falls back to keyword-only, which handles exact terms well and can miss conceptual matches on multi-word queries.2

The CLI

The anatomic-locations command takes either an identifier or a name at every subcommand.

CommandWhat it does
search "posterior cruciate ligament"Hybrid search, printing identifier, name, region, and laterality
hierarchy stomachAncestors above and descendants below the location, as a tree
children stomachDirect containment children, as a table
ancestors stomachContainment ancestors, nearest to root
descendants "abdominal cavity"Containment descendants
laterality "axillary lymph node"The sided variants of a generic location
code SNOMED 64033007Reverse lookup from an external code
statsDatabase path, record counts, region and code totals
$ anatomic-locations hierarchy stomach
 
whole body - RID39569
    └── abdomen - RID56
        └── peritoneal cavity - RID397
            └── ▶ stomach - RID114 ◀
                ├── gastric fundus - RID116
                └── pylorus - RID122

Where the database comes from

The DuckDB file is built separately from the JSON source, published to remote storage, and referenced from a central manifest.json that also carries the finding model index. On first use the package fetches it, checks the manifest for a newer version on later runs, and caches it locally.4 The path can be overridden with the ANATOMIC_DB_PATH environment variable or a db_path constructor argument, which is how a pinned build or a locally rebuilt database is used.1

What is not exposed

The MCP server in findingmodel offers three tools, all for finding models: search, get, and count. There is no anatomic location tool on it.5 An agent that needs locations calls the package directly or goes through findingmodel-ai, which exposes find_anatomic_locations for AI-assisted discovery.6

The older wrapper libraries

Both wrappers read the 2,890-record dataset described in lineage and current implementation, not the current one. Use them when you need the original data or a JavaScript runtime.

@talkasab/body_part_index installs from npm with the data bundled. It can also be constructed with a local JSON file of the same shape, and with a table of local codes mapped to RadLex identifiers, so an institution’s own body-part codes resolve through get() alongside SNOMED and FMA codes.7

import { BodyPartIndex } from '@talkasab/body_part_index';
 
const index = new BodyPartIndex();
const bodyPart = index.get('RID294');           // uterine adnexa
bodyPart?.getContainedBy();                     // RID2507, pelvis
bodyPart?.getPartOf();                          // RID270, female genital system
const left = bodyPart?.getLeft();               // RID294_RID5824

It carries the fullest hierarchy surface of any of the libraries: isContained and isPartOf tests, immediate and full children in both hierarchies, and full ancestors in both.7

BodyPartIndex.py is the Python counterpart. Its README states that installation from PyPI is pending, so it is used from source or with a local data file. It offers get() by identifier or code, get_by_code(), search() over names and synonyms, is_contained(), the laterality triad through left, right, and unsided, and a snomed_code property that falls back to the unsided version and then the immediate parent when the sided record carries no code of its own.8

The raw data

The project site publishes the curated set as a single JSON file with its JSON Schema and a changelog beside it, under the ISC license.9 That is the zero-dependency path, and the field meanings are in the data model and, verbatim, in the record format reference.

Footnotes

  1. anatomic-locations package README ↩ ↩2 ↩3

  2. Anatomic locations guide, findingmodel main ↩ ↩2

  3. Anatomic location assignment rules, imaging-problem-list dev ↩

  4. Rich anatomic location DuckDB with relationships ↩

  5. findingmodel MCP server ↩

  6. findingmodel-ai package README ↩

  7. BodyPartIndex.ts README ↩ ↩2

  8. BodyPartIndex.py README ↩

  9. anatomiclocations.org code page ↩