Skip to content

sct lookup

Look up a SNOMED CT concept by SCTID, reverse-resolve a CTV3 (Read v3) code, or resolve an ordered batch of codes from stdin.

When to use: you have an identifier and want the full concept record (preferred term, FSN, hierarchy, parents, attributes, maps). For text search, use sct lexical or sct fst; for set queries, use sct codelist add --ecl.


Usage

sct lookup <CODE|-> [--db <FILE>] [-f text|json|yaml]

Options

Argument / Flag Default Description
<CODE> (required) A numeric SCTID (e.g. 22298006), a CTV3 code (e.g. XE0Uh) for reverse lookup via the concept_maps table, or - to read one code per line from stdin.
--db <FILE> discovered (see Path resolution) SQLite database produced by sct sqlite.
-f, --format <FMT> text Output format: text (human), json, or yaml. (--json is a deprecated alias for --format json.)
--ids off Emit only the resolved SCTID(s), newline-delimited, for piping. With a CTV3 code, prints the mapped SNOMED concept id(s). Mutually exclusive with an explicit --format.
--provenance / --no-provenance auto Show or hide the release provenance footer (default: on for an interactive terminal).

Exit codes: an unresolved <CODE> (unknown SCTID, or a CTV3 code with no mapping) writes a hint to stderr and exits 1, so sct lookup fails loudly in scripts instead of succeeding with no output. Stdin batches are fail-closed: every input is resolved before stdout is written, so one invalid code exits 1 with empty stdout rather than leaving a partial result.

Check-digit validation: every SCTID's final digit is a check digit (the Verhoeff algorithm). A numeric <CODE> that fails this check but is otherwise not found gets a note appended to the error, flagging a likely typo. Set strict_sctid_checksum = true under [lookup] in config.toml (see Path resolution) to reject such codes outright, before querying the database.

Inactive concepts

A concept retired by SNOMED International is still resolvable - old records reference it - so sct lookup reports it rather than failing, and says both why it was retired and what to use instead:

  [9468002] Inactive example disorder
  ⚠ INACTIVE - Duplicate
    Replaced by: [22298006] Myocardial infarction
    Same as: [195967001] Asthma

In json/yaml the same information is inactivation_reason (an object with the value's id and human label, or null) and historical_associations (the RF2 association type, target SCTID, and the target's preferred term). Both are always present: null/empty for an active concept.

This needs a database built with sct ndjson --include-inactive --refsets all. Without --include-inactive the concept is absent entirely and lookup exits 1; without --refsets all the concept resolves and is flagged inactive, but the reason and replacements are unavailable, since they live in the AttributeValue and Association reference sets. Databases built before those refsets were ingested degrade the same way - flagged inactive, reason unknown - rather than failing.

The reason comes from the concept-inactivation indicator reference set (900000000000489007), not the parallel description-level one, and only from currently-active indicator rows: a superseded indicator is retained in the Snapshot and must not be read as current.


Examples

# By SCTID
sct lookup 22298006

# Raw JSON (for scripting / piping to jq)
sct lookup 22298006 -f json | jq '.preferred_term'

# Reverse lookup from a CTV3 code (requires a UK Monolith-derived database)
sct lookup XE0Uh

# Explicit database
sct lookup 73211009 --db /data/snomed.db
# Resolve a CTV3 code to its SNOMED SCTID for piping
sct lookup XE0Uh --ids

# Resolve an ordered batch while retaining each input/result association
printf '%s\n' 22298006 XE0Uh | sct lookup - --format json

CTV3 reverse lookup requires a database built from a UK edition that includes the CTV3 simple map refset; on an International-only database those codes won't resolve.

Batch input

Passing - reads the first whitespace-delimited token from each nonblank line, with a 64 KiB line limit, up to 10,000 entries and 100,000 retained results. Lines beginning with # are ignored, so both bare IDs and lines such as 22298006 |Myocardial infarction| can be piped in. Input order and duplicates are preserved; multiple CTV3 mappings are ordered by SCTID.

Text output writes input | resolved_sctid | preferred_term. --ids flattens the resolved SCTIDs in input order and cannot be combined with an explicit --format. JSON and YAML emit one document shaped as { "items": [{ "input": "...", "result": [...] }] }, which retains the boundary between inputs. Supplying one code directly keeps the existing single-concept output shape.