OpenCodelists

Documentation

Welcome to the documentation for OpenCodelists, part of the OpenSAFELY project from the Bennett Institute for Applied Data Science at the University of Oxford.

OpenCodelists is an open platform for creating and sharing codelists of clinical terms and drugs.

Table of contents

Status of the project

OpenCodelists has been used to create 12124 codelists since April 2020, and it is in active development by staff at the Bennett Institute.

Codelists created with OpenCodelists are used in research projects all over the UK, both within and without the OpenSAFELY research ecosystem.

Anybody can use OpenCodelists to create and share codelists.

To report bugs or suggest improvements, please raise an issue via the issue tracker on GitHub.


What is a codelist?

A codelist is a set of codes which can be recorded in clinical systems, representing data such as:

  • Patient Demographics - e.g. Age, Ethnicity
  • Medicines - e.g. Paracetamol, Morphine
  • Condition Diagnoses - e.g. Crohn's Disease, Bipolar disorder
  • Symptoms - e.g. Headache, Blood in urine
  • Test Results - e.g. Potassium level, Abnormal ECG
  • Procedures - e.g. Coronary artery bypass graft, Hysterectomy
  • Activities - e.g. Medication review, Consultation via video

Codelists are used in almost all studies in OpenSAFELY - and other health data research - to select patients with activities and conditions of interest within the dataset(s) being used.

  • Codelists each use a coding system such as SNOMED CT, dm+d (dictionary of medicines and devices), CTv3 (Clinical Terms v3), etc.
  • Codelists can often be large, in order to capture the many possible codes that could represent a certain activity or condition.
  • Creating or selecting a codelist can often be very nuanced, e.g. whether a codelist for "diabetes" should include or exclude gestational diabetes may vary according to the study.
  • Sometimes a combination of codelists of different types may be required to fully capture patients with certain conditions, e.g. medications for asthma (dm+d), diagnoses of asthma in primary care (SNOMED CT), diagnoses of asthma in a hospital admission (ICD-10).

Viewing a codelist

The homepage of a codelist shows:

  • information about what the codelist contains,
  • how the codelist was created,
  • links to any references
  • details of who created the codelist

Codelist IDs and versions

The codelist homepage also displays:

  • the codelist's ID
  • current version information.

A codelist has a Codelist ID, which is the canonical ID for the codelist and determines the URL of its homepage. For example, if it existed, the above codelist would be found at https://opencodelists.org/codelist/user/bob/asplenia. This URL will always go to the latest visible version; if you are logged in and you have a version of the codelist in draft or review, this will be shown. Otherwise, it will go to the latest published version.

A codelist can have multiple versions, each of which has a Version ID (and also a Version Tag for some older codelists). The ID and tag (if applicable) for the version that you are currently viewing is also displayed under the Codelist ID.

If there are multiple versions of a codelist, links to these will be displayed:

The codelist details tabs

The Full list tab shows a searchable list of codes and terms.

Most codelists have a Tree tab, showing all of the codes in the codelist in the context of other codes in the coding system. This is helpful for seeing whether there are any accidental gaps in the codelist.

  • Codes that are in the codelist have an "Included" label
  • Codes that are not in the codelist are shown greyed out and have an "Excluded" label

For codelists that were created with the builder, there will also be a Searches tab, showing the search terms that were used to create the codelist.

For all codelists, there are links for downloading a CSV of the codelist and a CSV containing a definition of the codelist.


Creating an account

You do not need an account to view codelists, but you do to create codelists.

Anybody can create an account. To do so, click the Sign up menu option.


Organisations

If you are a member of an OpenCodelists organisation, you will see a My organisations menu option.

My organisations allows you to view codelists that are owned by your organisations, or that are waiting for review.

Any OpenCodelists user with an account can create a codelist. However, to create or edit codelists on behalf of an organisation, you must be a member of that organisation.

To join an organisation:

  • Contact your organisation administrator.
  • Your administrator will need your OpenCodelists username or email address in order to add you to the organisation.

Creating a codelist from scratch with the codelist builder

Our codelist builder tool helps you create a codelist from scratch, by searching terms and choosing which matching concepts should be included.

When signed in, click the My codelists menu option.

Then click Create a codelist.

This will take you to a form to create a new codelist.

Choose a name for the codelist, and select a coding system. We currently support codelists using the following coding systems:

If you are a member of an organisation, you can also choose an owner for the codelist (your own account or an organisation account).

Then click Create.

You'll be taken to the codelist builder tool, with instructions displayed.

Build your codelist by searching for terms or codes, and then choosing which of the matching concepts should be included in the codelist. Choose between searching for a code and a term with the Term and Code buttons above the search text entry.

Any concepts that match your search term, and their descendants, are shown in a hierarchy.

To keep the page manageable, only two levels of the hierarchy are initially visible. You can further expand the hierarchy by clicking the button next to concepts.

Include a concept by clicking the + button, and exclude a concept by clicking the button. When you include or exclude a concept, all of its descendants are also included or excluded. Explicitly included/excluded concepts have buttons highlighted blue; their descendants have buttons highlighted grey.

To undo inclusion or exclusion of a result, click on the include or exclude button again.

Sometimes a code can be in conflict. This happens when one of its ancestors in included and another is excluded. For instance, Arthritis of elbow is in conflict because it is both a descendant of the included Arthropathy of elbow, and the excluded Elbow joint inflamed.

Hover on a conflicted code and click More info to see the conflict details.

Under Concepts found there are a link to filter the builder view to conflicted or unresolved concepts.

All the searches used to build the codelist are displayed under Previous searches. View the results of specific searches again by clicking on them. The show all button returns to the combined results of all searches.

Delete a search by clicking the Remove button next to it. If you have already included some concepts from that search, they will not be removed.

The save buttons are at the top of the builder:

If you have not yet completed your codelist, you can Save draft at any time, and return to edit it later. Once you have included or excluded every search result and have no remaining conflicts, the Save for review button will be enabled. The Save for review button takes you to the codelist's homepage, where you can edit metadata to provide:

  • a description
  • methodology
  • links to references
  • codelist sign offs

The codelist is still not publicly available to allow for it to be reviewed and signed off. You can copy its URL and send it to a another OpenCodelists user to review. The reviewer signs off by editing the codelist's metadata, and adding their user and the date in the sign offs section.

Procedures for reviewing and signing off codelists may vary between organisations. For more information on procedures for building codelists to use in OpenSAFELY research, see the OpenSAFELY documentation.

Once the codelist is reviewed, it can be published, using the Publish version button from the codelist's homepage:

Publishing a codelist version will make that version permanent, and will delete any other draft or in-review versions.

Notes on building dm+d codelists

The builder functions largely the same with the dm+d coding system as with any other coding system, save for few minor details listed here.

Searches will be executed across Ingredient, VTM (Virtual Therapeutic Moeity), VMP (Virtual Medicinal Product), and AMP (Actual Medicinal Products) entities' codes or names (and descriptions, where available).
Whilst Ingredients are searched, they are not displayed in the results. However, any VMPs containing an Ingredient that matches a search will be displayed (along with their related VTMs and AMPs).

Codes are arranged in the tree view based on a hierarchy of VTM -> VMP -> AMP.
Due to the large number of AMPs for many VMPs, this part of the tree is not expanded by default but can be by clicking the small plus arrow next to the VMP whose AMPs you wish to view.

Historical dm+d codelists uploaded from csv or converted from Pseudo-BNF codelists are not fully enabled for editing in the builder.
By default, it is only possible to create new versions of these codelists by uploading a new csv file, or by re-running a conversion from Pseudo-BNF.
We can, on request, convert these historical codelists into ones that are fully enabled in the builder for creation of new versions.


Creating a codelist from a CSV file

As well as creating a codelist from scratch, you can create one by uploading a CSV file.

From the My codelists page, click Create a codelist.

  1. Choose a name for the codelist.
  2. Select a coding system.
  3. Press the + next to "Upload CSV" in the "Upload a CSV" section to show the CSV upload options.
  4. Choose a file to upload from your hard drive.
  5. Specify whether or not your CSV has a header row or not.

To create an OPCS-4 codelist, please see the notes elsewhere on this documentation page.

If you are a member of an organisation, you can also choose an owner for the codelist (your own account or an organisation account).

Requirements for uploading codelists to OpenCodelists via the "Create a codelist" form

  • Store the final codelist in CSV format.
  • Store codes in the first column: only the first column is processed by the form.
  • Check whether or not your codelist has a header row: you will need to specify this on upload.

Potential issues when editing codelists in spreadsheet software, such as Excel

Avoid:

  • filtering on an include or exclude column when finalising a codelist. Applied filters are lost in CSV conversion: all of the codes will be uploaded.
  • editing SNOMED CT codelists. The codes get rounded.

When you click Create the codelist will be created and you will be taken to the codelist homepage.

From here, you can edit any metadata. You can also edit the codelist.

We are aware of an issue whereby Excel can truncate or round dm+d IDs, turning them into invalid IDs. This is due to Excel's interpretation of this column as a number type insufficiently large to contain a dm+d ID. For this reason, opening dm+d codelist files in Excel should be avoided wherever possible.

Where it is unavoidable to do so, rather than opening a dm+d codelist csv file directly in Excel (such as through the Open dialogue or from the file explorer), we recommend opening a blank Excel workbook and using the "Import data from Text/CSV" feature. To avoid the problematic rounding/truncation behaviour described above, specify the data type of the dm+d id column as "Text" during the import process.

Adding an OPCS-4 codelist

Note: OPCS-4 codelists can not currently be created using the "Create a codelist" form described above.

To add an OPCS-4 codelist, navigate to https://www.opencodelists.org/codelist/{ACCOUNT}/add/ — where {ACCOUNT} in the URL is substituted with one of the following options:

  • Either user/{username} where username is your OpenCodelists username, to add the codelist to your personal account
  • Or the name of the organisation your account is associated with, to add the codelist under the organisation.

The OPCS-4 codes you upload should NOT include the decimal point.

More about codelist columns

The codelist /add/ page allow you to upload multiple columns such as:

  • a code
  • a text description of the code

Some codelists may require a 'classification' or 'type' column, which classifies the codes into subcategories. For example, when using a codelist for venous thromboembolism, you may wish to classify these codes into deep vein thromboses and pulmonary embolisms. By using subcategories, you can keep all the codes in a single codelist, rather than uploading separate lists for each clinical subcategory. The OpenSAFELY documentation has guidance for using category columns with OpenSAFELY ehrQL dataset definition.


Selecting appropriate codes for your codelist

Choosing which codes to include in your codelist can be challenging without understanding their usage in clinical practice.

Some clinical activities are represented by a single code, while others may require a comprehensive list of codes to accurately capture the intended clinical activity. Even a single incorrectly included or omitted code could potentially lead to vastly different results when using the codelist to query electronic health record data.

Some of the common pitfalls when selecting appropriate codes include:

  • Including similar-sounding but unrelated codes. For example, ocular hypertension, which pertains to high fluid pressure within the eye, and is not appropriate for a codelist intended to capture high blood pressure.
  • Omitting synonyms. For example, when defining a codelist for sore throat, it is essential to include clinical codes which describe pharyngitis as well.
  • Misunderstanding study intent. Selecting an appropriate codelist requires careful consideration of which patients are relevant to the research aims. For example, the decision to include or exclude gestational diabetes in a diabetes codelist may vary depending on the specific study or context.
  • Use of non-specific codes. Some codes might be useful to improve sensitivity of a study but care needs to be taken to consider potential negative impact on specificity. For example, sore throat is a potential symptom of Group A Strep infection but is also a symptom of many other conditions, if including this in a study it is likely other codelists (for example, antibiotics for Group A Strep treatment) would need to be used to maintain an appropriate level of specificity.

To avoid these pitfalls we recommend:

  • Clearly defining your clinical feature of interest. This may include specific features you do not want to capture.
  • Specifying the synonyms that may be used for your clinical feature of interest.
  • Considering balancing sensitivity and specificity of the selected codes
  • Looking for similar codelists on OpenCodelists and understanding what methodology they used for their selection of codes.
  • Where available, using published data on code usage to understand how a clinical area is coded in practice. This doesn't exist for all code terminologies, but helpfully, NHS Digital provides a dataset on SNOMED CT code usage in primary care, which includes data since 2011. This dataset includes annual counts of how often each SNOMED CT code is recorded in GP patient records across England. You can explore recorded usage of individual codes or entire codelists, including those on OpenCodelists, using this prototype SNOMED CT code usage explorer. Note, however, that low or no usage for a code may not be indicative of its future use.

You can read more about codelists and their construction in the Bennett Institute blog series on clinical codes.


Editing a codelist

You can edit a codelist that you own, or that is owned by an organisation that you belong to. To do this, click Create new version on the codelist homepage.

This will open the builder, with all of the codes from your codelist selected. Additionally, if the codelist was created through the builder, then any terms that were searched for will be present.

You can search for new terms, and you can change whether any concepts are included or excluded.

You can discard your changes by clicking Discard. You can also save a draft version of your codelist by clicking Save as draft. And when all concepts have been resolved, you can save your changes and create a new version for review by clicking Save for review.

Importantly, the original version of your codelist is still accessible at the same URL.


Viewing your codelists

You can view your codelists the My codelists page.

This page shows a list of all your published codelists, organisation codelists that you have created or edited, and your codelists that are currently in draft or under review.


Cloning a codelist

You can make a clone, or copy, of any published codelist that is owned by an organisation, another user, or even yourself. You may also clone a codelist that is not yet published if you also have permission to edit it. To clone a codelist, click Clone this codelist on the codelist homepage.

This will create a clone of the most recent version of this codelist in your codelists, with the same name as the source codelist, and all of its metadata (including a link back to the source codelist).

If you clone one of your own codelists, to avoid a clash of names (clone) will be added to the codelist name, plus a number if you make further clones of that clone.

You may now make edits to this clone, including creating new versions, just as if it were a codelist you had created from scratch.


Diffing a codelist

You can compare which codes are present in two different codelist versions using the diff function.

By convention, the first codelist version you wish to compare is referred to as the "left hand side" (LHS) of the comparison and the second the "right hand side" (RHS).

Start by going to the page of the codelist version you wish to be the LHS, then append /diff/ to its URL and then the Version ID of the codelist version you wish to be the RHS. This RHS version can be a different version of the same codelist, or a version of an entirely different codelist - so long as they are both defined in the same coding system.

For example, in order to compare these two versions of the same codelist: https://www.opencodelists.org/codelist/opensafely/alanine-aminotransferase-alt-tests-numerical-value/16fdc2da/ and https://www.opencodelists.org/codelist/opensafely/alanine-aminotransferase-alt-tests-numerical-value/78d4a307/, take the full URL of the first, add /diff/ then the id of the second ("78d4a307" in this case) to give the diff URL of https://www.opencodelists.org/codelist/opensafely/alanine-aminotransferase-alt-tests-numerical-value/16fdc2da/diff/78d4a307/.

To compare this codelist version https://www.opencodelists.org/codelist/opensafely/alanine-aminotransferase-alt-tests-numerical-value/16fdc2da/ to this version of a related but different codelist https://www.opencodelists.org/codelist/opensafely/alanine-aminotransferase-alt-tests/11d2e678/ the resultant diff URL would be https://www.opencodelists.org/codelist/opensafely/alanine-aminotransferase-alt-tests-numerical-value/16fdc2da/diff/11d2e678/.

N.B: If a codelist version has been assigned a Tag, then the URL for that version will default to containing that Tag rather than the Version ID. For the LHS version, this is not a problem, but attempting to use a Tag in place of a Version ID in the diff URL for the RHS may result in unexpected errors. The Version ID for a codelist version is visible in the table of information at the top of its page.


ICD-10 editions and updating codelists

OpenCodelists combines the two ICD-10 editions used in OpenSAFELY data:

Why have you combined the two editions?

Most ICD-10 codes have the same meaning in both editions. Codelists are also often used with more than one dataset. Asking people to choose an edition when creating a codelist would likely be confusing, and would lead to parallel codelists. It would be easy to use a codelist built against the wrong edition, which could lead to missed events.

OpenCodelists therefore provides a single ICD-10 coding system containing codes from both editions. This means that in most cases, a single codelist can be used against any dataset. Where there are differences, OpenCodelists provides warnings and guidance.

When did this happen?

Originally, OpenCodelists only supported the WHO 2019 edition. The switch to the combined ICD-10 coding system was made in September 2026.

What are the differences between the two editions?

Most codes are identical in both editions. The differences that need further attention are:

  1. Moved codes: Concepts with different codes in different editions
  2. Changed definitions: Codes with a different definition

Moved codes

There are ~20 codes that have moved between the two editions. For example, the concept of "Pneumocystosis" is coded as B59 in the 2016 edition , but B48.5 in the 2019 edition. Fortunately, there are no instances where a code has been reused for a different concept in the other edition. This means that it is safe to include the code from both editions in a codelist, irrespective of which edition is used in the dataset being queried. A codelist with both B59 and B48.5 will match events in ONS deaths with B48.5 and events in admissions data with B59.

This is of particular note for codelists involving COVID-19. The codes for "virus identified" and "virus not identified" are the same in both editions (U07.1 and U07.2), but there are 5 other codes covering history of COVID-19, long COVID, need for vaccination etc which are U07.3-U07.7 in the NHS 2016 edition, but U08-U12 in the WHO 2019 edition.

Changed definitions

There are two categories of changed definition:

  • minor wording differences/typos
  • clinically significant differences.

The former are not a concern, e.g. "Cow milk" vs "Cow's milk". However, the latter can lead to a codelist including events incorrectly. For example, the code X59.0 will match fractures in ONS deaths because the 2019 edition defines it as "Exposure to unspecified factor causing fracture" but that same code in admissions data is defined in the 2016 edition as "Exposure to unspecified factor (occurrence at home)". A codelist for fractures would want to include that code for ONS deaths, but exclude it for admissions data.

How have you resolved the definition differences?

Where the same code has a different definition:

  • we store both definitions in the OpenCodelists coding system;
  • we display the NHS 2016 definition by default;
  • we provide both definitions in the More info panel; and
  • if the definitions are more than minor wording differences, we display a warning banner with instructions on how to proceed.

Understanding the warning messages

We provide warnings when:

  • a codelist contains a code from one edition, but not the corresponding code from the other edition e.g. it contains the NHS 2016 code but not the equivalent WHO 2019 code
  • a codelist includes a code that has conflicting definitions in the two editions.

Warnings mean that a codelist needs review. They do not necessarily mean that the codelist is wrong.

If a concept moved to a different code

The warning looks like this:

The warning lists the codes used for the concept in each edition and highlights the codes missing from the codelist.

For a codelist intended to work across admissions and ONS deaths data, the safest approach is normally to include all the listed codes. Codes identified as moved are not reused for unrelated conditions in the other edition.

Check every suggested code against the purpose of the codelist before adding it. Some groups need a more specific decision. For example, the 2019 edition divides irritable bowel syndrome into more detailed subcategories, so a codelist specifically about diarrhoea or constipation may need only part of the group.

If there is a valid reason to not include all codes for a concept, then the warning will remain. It is therefore important to update the methodology section of the codelist's metadata to explain the reason for the decision for future reference.

If a code has conflicting definitions

The warning looks like this:

The warning lists the code and both definitions. It is important to check the definitions against the purpose of the codelist and the dataset(s) it will be used with. The codelist may need to be updated to exclude the code, depending on which of the following situations applies:

  • Both definitions are relevant: If the purpose of the codelist is such that both definitions are appropriate, then retain the code in the codelist. The warning will remain, so it is important to record the reason for the decision in the codelist methodology for future reference.
  • Only the NHS 2016 definition is relevant:
    • If the codelist is intended for admissions data only, then include the code in the codelist. Please clearly state in the methodology section of the metadata that the codelist is intended for admissions data only, and that it should not be used for ONS deaths data.
    • If the codelist is intended for ONS deaths data only, then exclude the code from the codelist. Please clearly state in the methodology section of the metadata that the codelist is intended for ONS deaths data only, and that it should not be used for admissions data.
    • If the codelist is intended for both admissions and ONS deaths data then you will need to create separate codelists for each dataset. Please clearly state in the methodology section of the metadata of each codelist which dataset it is intended for, and that it should not be used for the other dataset.
  • Only the WHO 2019 definition is relevant:
    • If the codelist is intended for ONS deaths data only, then include the code in the codelist. Please clearly state in the methodology section of the metadata that the codelist is intended for ONS deaths data only, and that it should not be used for admissions data.
    • If the codelist is intended for admissions data only, then exclude the code from the codelist. Please clearly state in the methodology section of the metadata that the codelist is intended for admissions data only, and that it should not be used for ONS deaths data.
    • If the codelist is intended for both admissions and ONS deaths data then you will need to create separate codelists for each dataset. Please clearly state in the methodology section of the metadata of each codelist which dataset it is intended for, and that it should not be used for the other dataset.

Converting Pseudo-BNF codelists to dm+d

Pseudo-BNF and the NHS Dictionary of Medicines and Devices (dm+d) are both medication coding systems in regular use in the UK.

The NHS regularly publishes a file which maps BNF codes to dm+d codes, which we ingest into OpenCodelists, allowing you to convert your Pseudo-BNF codelists to dm+d.

To convert a Pseudo-BNF codelists to dm+d:

  1. Go to the page for Pseudo-BNF codelist you wish to convert.
  2. If there are multiple versions of the Pseudo-BNF codelist, select the relevant codelist version.
  3. Click the "Convert to dm+d" button.

This will create a new codelist with the same name as your Pseudo-BNF codelist but with a "-dmd" suffix, and you will be taken to its page. The methodology statement of this dm+d codelist contains a link back to your original Pseudo-BNF. As with any other codelist, you are free to edit this statement, and all other codelist metadata.

If you wish to update this converted codelist (for example, after an update to the Pseudo-BNF list, the Pseudo-BNF coding system, or the Pseudo-BNF to dm+d mappings):

  1. Return to the Pseudo-BNF codelist.
  2. Click the "Convert to dm+d" button again

A new version of the dm+d codelist will be created.

If this new version is identical to an existing version of the codelist (i.e. there are no changes in the dm+d codes), you will be shown an error and the new version will not be created.


Using a codelist in OpenSAFELY research

Codelists are central to the research that is carried out in OpenSAFELY.

For more information about using codelists in OpenSAFELY research, see the OpenSAFELY documentation.


Reporting bugs, requesting features, and asking for help

If you've found a bug or would like to request a feature, please raise an issue in the issue tracker on GitHub.

If you'd like support, try asking in the OpenSAFELY discussion forum.