Home Manifesto Blog Join the beta

The 23andMe API Is Gone: Reading 23andMe Data in Python

The Short Answer

There is no 23andMe API you can sign up for in 2026. What still works is the raw data file the customer downloads, and every tool that reads 23andMe data today, from PLINK to bcftools to the Python package snps, starts from that file.

TL;DR:

  1. Don't build on api.23andme.com: it no longer serves the genetic endpoints.
  2. Ask the user for their raw data download (a .zip with a genome…txt inside).
  3. Parse four columns: marker, chromosome, position, genotype. Positions are GRCh37, so remap before joining against GRCh38 data.
  4. Treat -- as "no call", and expect single-letter genotypes on X, Y and MT and marker IDs that start with i.

23andMe told developers in August 2018 that it was turning off third-party access to genetic data. Today the host redirects to the company's main site and the old documentation paths return 404, which you can check yourself:

# 302: the host redirects away
curl -sI https://api.23andme.com/ | head -1
# 404: the old API reference is gone
curl -s -o /dev/null -w "%{http_code}\n" \
  https://api.23andme.com/docs/v1_reference/

What Happened to the 23andMe API

23andMe opened its API to developers in September 2012. It was an OAuth 2.0 API: an app asked the customer for permission, then read their data on their behalf. The v1 reference, by then already marked deprecated, listed endpoints such as /1/genotypes, /1/genomes, /1/haplogroups and /1/ancestry. The /genomes endpoint returned the customer's whole genotype as one packed string of roughly 2 MB. A later v3 reorganised this around /3/marker, /3/variant and /3/report.

On 23 August 2018 23andMe told developers it would disable that access within two weeks. From then on, third-party apps could no longer pull a customer's raw genotypes; research partnerships kept their own arrangements. An archived copy of the developer portal from January 2023 says access is granted only through a developer arrangement and points to a business-development address.

Two events since then make it unlikely to come back in its old form:

The open-data side shrank too. openSNP, where people published their own 23andMe files for researchers, shut down on 30 April 2025 and deleted its data, citing the bankruptcy among its reasons.

So if a tutorial, a GitHub repo or an LLM tells you to register an app at api.23andme.com, it is describing something that hasn't existed for years.

The Replacement: the Raw Data File

The customer downloads their own data and hands it to your software. 23andMe's help page describes the route: in the account, Browse Raw Genotyping Data, then Download, with a date-of-birth confirmation. Preparing the file "usually takes about one week but can sometimes take up to thirty days". What arrives is a .zip holding a text file whose name starts with genome.

This changes your product more than your code. With the API, consent was an OAuth screen and the data arrived in seconds. With the file, the user has to request it, wait up to a month, and then upload it to you. Build the wait into the onboarding (the steps are in our guide to 23andMe raw data), and tell the user exactly which file to send you, because people often upload the .zip, a screenshot or a PDF report instead.

It also changes your responsibility. The file is the user's whole genotype, and once they upload it you are the one holding it. Keep only what your feature needs, and delete the upload once you've parsed it.

What's in the File

Each data line has four fields: a marker name, a chromosome, a position and a genotype. Lines starting with # are a comment header to skip. Here is a synthetic example we made with the same shape (the parser below splits on any whitespace, so it doesn't depend on the exact separator):

# This data file generated by 23andMe at: Sun Oct 11 12:00:00 2026
#
# rsid	chromosome	position	genotype
rs4244285	10	96541616	AG
rs1801133	1	11856378	AG
rs429358	19	45411941	TT
rs7412	19	45412079	--
i5000100	X	2700157	A
i5000200	Y	2655180	G
i5000300	MT	16519	C

The i… rows are made up for illustration; the rs rows use real GRCh37 positions. Four details in that file break naive parsers, all of them documented by 23andMe itself:

Which markers a file contains depends on the chip the customer was genotyped on. 23andMe's own chip documentation lists four generations, from about 560,000 variants on v2 to the current v5, built on Illumina's Global Screening Array with about 654,000 preselected variants plus about 50,000 custom ones. Two customers' files won't contain the same set of markers, so check that a marker is present before you report on it.

Parsing It in Plain Python

This reader has no dependencies and refuses to guess. It keeps the i IDs, stores no-calls as an empty string, keeps haploid calls as they are, and fails loudly on anything that isn't four columns or a known chromosome, which is how you find out a user uploaded the wrong file:

from dataclasses import dataclass
from pathlib import Path

VALID_CHROMS = {str(n) for n in range(1, 23)} | {"X", "Y", "MT"}


@dataclass(frozen=True)
class Call:
    marker: str      # rsID, or a 23andMe internal ID starting with "i"
    chrom: str
    pos: int         # GRCh37 coordinate
    genotype: str    # "AG", "T" (haploid) or "" (no-call)


def read_23andme(path: str | Path) -> list[Call]:
    calls = []
    with open(path, encoding="utf-8") as fh:
        for n, line in enumerate(fh, 1):
            if line.startswith("#") or not line.strip():
                continue
            fields = line.split()
            if len(fields) != 4:
                raise ValueError(f"line {n}: expected 4 columns, got {len(fields)}")
            marker, chrom, pos, gt = fields
            if chrom not in VALID_CHROMS:
                raise ValueError(f"line {n}: unknown chromosome {chrom!r}")
            calls.append(Call(marker, chrom, int(pos), "" if gt == "--" else gt))
    if not calls:
        raise ValueError("no genotype rows: is this really a 23andMe file?")
    return calls

On the synthetic file above it returns seven calls. Four are rsIDs, one of them a no-call (rs7412); the other three are the i rows, which are also the three single-letter calls. On the CYP2C19 row it gives Call(marker='rs4244285', chrom='10', pos=96541616, genotype='AG').

If you take uploads, add two more checks before trusting the result: unzip the .zip yourself rather than asking the user to, and look for 23andMe's own first comment line, since an AncestryDNA or MyHeritage file can also have four or five columns.

Remapping to GRCh38 With snps

For anything beyond reading the file, the open-source snps package (version 2.12.1, actively maintained) already handles the format. It recognises 23andMe files, detects the build, and remaps coordinates using Ensembl's assembly mappings:

from snps import SNPs

s = SNPs("genome_synthetic.txt")
print(s.source, s.build, s.count)   # 23andMe 37 7

s.remap(38)                          # downloads Ensembl mapping data
print(s.snps.loc["rs4244285"].to_dict())
# {'chrom': '10', 'pos': 94781859, 'genotype': 'AG'}

We ran this on 11 October 2026, and the GRCh38 position it returns matches Ensembl's record for rs4244285. The no-call on rs7412 comes back as NaN, so filter it out before you count genotypes. remap needs network access the first time it runs. If your machine sits behind a proxy that rewrites TLS certificates, point SSL_CERT_FILE at a certificate bundle such as certifi's.

snps can also write a VCF, and so can bcftools, whose manual uses a 23andMe file as the example for convert --tsv2vcf. Both need a GRCh37 reference to fill in reference alleles, and neither turns the file into an interpretation. A VCF of 650,000 genotypes still says nothing about what a single one of them means.

What the File Doesn't Give You

The old API returned some interpretation alongside the genotypes, such as haplogroups and ancestry composition. The raw file contains only the genotypes, so everything else is now your job.

The file says AG, but whether A is the allele that matters, and on which strand the literature reports it, has to come from ClinVar, dbSNP or a curated source. The call itself is reliable for common variants and much less so for rare ones: a 2021 study in the BMJ compared SNP chip calls with sequencing in about 50,000 UK Biobank participants: for variants rarer than 0.001%, only 16% of the heterozygous calls from the chips were confirmed by sequencing. A rare, alarming call from a consumer chip needs a clinical test before anyone acts on it. And a marker that isn't on the chip is not a negative result.

If your code is an AI agent, this is also where it is most likely to go wrong: asked what rs4244285 AG means, a model will answer from memory. Giving it a lookup tool with cited sources is safer than trusting recall.

Where DeepDNA Fits

DeepDNA, which is not affiliated with 23andMe, runs free knowledge endpoints with no key. They cover 12 genes today, mostly pharmacogenes plus a few of the most-searched nutrition and risk genes. Each record cites its sources:

curl -s https://deepdna.ai/api/v1/variants/rs4244285

That returns the CYP2C19 *2 record: what the A allele does, a reading block with the reference and variant alleles on the plus strand of GRCh37 (the orientation of the file you just parsed), a short note on population frequency, and links to the CPIC and PharmVar pages it was written from. The same lookups are exposed as a remote MCP server at https://deepdna.ai/mcp, so an agent can call them as tools. The request carries an rsID or a gene name, never a genotype or a file.

Parsing files is a different matter. POST /dna/parse, an endpoint designed to take a raw file from 23andMe, AncestryDNA or MyHeritage and return normalised variants, is in private beta and not deployed: it doesn't answer today, with or without a key. Until it does, the reader above and snps are the honest answer. The API docs list what is live, and for a worked example that goes from a raw file to CPIC phenotypes, see CYP2C19 and SLCO1B1 from a raw DNA file in Python.

Frequently Asked Questions

Does 23andMe have an API?

Not one you can use. 23andMe turned off third-party access to genetic data in 2018, by 2023 access required a direct business arrangement, and in 2026 api.23andme.com redirects away from the old developer site. The supported way to get a customer's genotypes is the raw data file they download themselves.

When did the 23andMe API shut down?

23andMe told developers on 23 August 2018 that it would disable access within two weeks. The documentation paths that served the API reference now return 404.

What format is the 23andMe raw data file?

A text file with # comment lines, then four whitespace-separated columns per marker: rsID or internal i ID, chromosome, position and genotype. Positions are GRCh37 on the plus strand, -- means no call, and mitochondrial calls, plus most X and Y calls in men, have a single letter.

Is 23andMe raw data GRCh37 or GRCh38?

23andMe documents the raw data as GRCh37 on the plus strand. Its online Browse Raw Data view now also shows GRCh38 genotypes, so check the build of any file you receive. The snps package detects it for you and can remap to GRCh38.

Can I convert a 23andMe file to VCF?

Yes. Both snps and bcftools convert --tsv2vcf can do it, given a GRCh37 reference. A VCF makes the file readable by more tools but doesn't add any interpretation.


This article is for educational purposes only and does not constitute medical advice. Consumer genotyping arrays can miss or miscall variants, especially rare ones; any finding that could affect health decisions should be confirmed by a validated clinical test and discussed with a qualified clinician.

This article was created with AI assistance and reviewed by the DeepDNA editorial team.

DNA and bloodwork, as an API

DeepDNA is now an API for AI agents and health apps. The knowledge endpoints are live and free, no key. Parsing DNA files and lab reports, and crossing the two, is in private beta. Building something with genetic or lab data? Tell us what.

Read the API docs
or request a beta key

DeepDNA is now an API.

For the agents and apps you use, not for reading your file yourself. The knowledge endpoints are live and free, no key. Parsing DNA files and lab reports, and crossing the two, is in private beta. Building something with genetic or lab data? Tell us what.

Read the API docs
or request beta access
DeepDNA is now an API. Knowledge endpoints free; private beta for builders. API docs