Proteins API

Programmatically accessing MGnify Proteins data via the Proteins Web API
Author
Affiliation
Published

September 23, 2026

MGnify Proteins API

Introduction

The MGnify Proteins API provides programmatic access to the data presented on the MGnify Proteins portal: the metadata held for each cluster representative in the MGnify Protein Database, and a way to search for cluster representatives by biome or by Pfam domain.

This API is synchronous and read-only: every request is a single GET that returns JSON. No authentication or API key is required.

The API is intended for looking up and exploring individual proteins and small result sets. If you need to fetch more data, bulk downloads are available from the Transfer Services file server, and the whole database can be queried remotely, without downloading it, using Parquet and DuckDB.

Note

Note that detailed records exist only for cluster representatives, not for every protein sequence in the database. See MGnify Proteins Resource for an explanation of the clustering.

API Overview

Current version

The current API version is v1.

Base URL

The base address for the API is:

https://www.ebi.ac.uk/metagenomics/proteins/api/v1

Interactive documentation

An interactive Swagger UI is served alongside the API, listing every endpoint, parameter and response schema, and allowing requests to be issued from the browser:

The OpenAPI schema can be used to generate a client in your language of choice, with a tool such as OpenAPI Generator.

HTTP methods

The API is read-only: only GET is supported.

Endpoints

There are two endpoints:

Endpoint Purpose
GET /protein/{mgyp} The record held for one cluster representative — see Protein detail
GET /protein/search Find cluster representatives by biome or Pfam domain — see Protein search

Errors

Errors are returned with a conventional HTTP status code and a JSON body:

Status Meaning
302 The requested MGYP is no longer a cluster representative and has been superseded by another; the Location header carries the replacement accession. Pass curl -L to follow it automatically.
404 The MGYP accession is malformed, or no such cluster representative exists
422 The query parameters are invalid: no filter given, more than one filter given, limit out of range, or a biome_lineage that matches no biome
Warning

The detail field has two shapes. Errors raised by the endpoint itself carry a plain string:

{"detail": "No biome matches lineage 'Wastewater'. Provide a full lineage such as 'root:Engineered:Wastewater'."}

Errors caught during automatic parameter validation carry a list of objects instead:

{"detail": [{"type": "value_error", "loc": ["query"], "msg": "Provide exactly one of biome_id or pfam_accession or biome_lineage"}]}

Client code that displays error messages should handle both.

Protein detail

GET /protein/{mgyp}

Returns the full record for a single cluster representative, the same information shown on its detail page, excluding the predicted 3D structure.

The {mgyp} path parameter is an MGYP accession. It is tolerant of formatting: MGYP000261684433, mgyp000261684433 and 261684433 all resolve to the same protein.

Response fields

  • mgyp: the MGYP accession, e.g. MGYP000261684433.
  • sequence: the amino acid sequence of the cluster representative.
  • full_length: whether the sequence is a full-length ORF (true) or a fragment (false).
  • cluster_size: the number of protein sequences in this cluster.
  • biomes: the biomes this protein was observed in, each with an id, a name (the full lineage) and a count of occurrences. The id is the value to pass to the search endpoint’s biome_id parameter.
  • pfam_annotations: Pfam domains matched within the protein — accession, name, clan, evalue, bit_score, and the hmm_start/hmm_end and env_start/env_end coordinates.
  • study_assembly_contigs: where the protein was found — the study and assembly accessions, the contig accession and name, the start/end coordinates and the strand.

Example

curl "https://www.ebi.ac.uk/metagenomics/proteins/api/v1/protein/MGYP000261684433"
{
  "mgyp": "MGYP000261684433",
  "sequence": "EESGVTRAVQGAGDEVPGEVFFEKGVVEETLRGGPAGEAAAGDTEAATAET...GDGDVSVERLL",
  "full_length": false,
  "cluster_size": 1,
  "biomes": [
    {"count": 1, "id": 132, "name": "root:Environmental:Aquatic:Marine"}
  ],
  "pfam_annotations": [
    {
      "accession": "PF04659",
      "name": "Archaeal flagella protein",
      "clan": null,
      "evalue": 1.1301790139316117e-22,
      "bit_score": 87.55205535888672,
      "hmm_start": 2,
      "hmm_end": 95,
      "env_start": 325,
      "env_end": 412
    }
  ],
  "study_assembly_contigs": [
    {
      "study_accession": "ERP108403",
      "assembly_accession": "ERZ534239",
      "contig_accession": "MGYC000564781877",
      "contig_name": "ENA-OSOD01046483-OSOD01046483.1-marine-metagenome-genome-assembly--contig:-NODE-46483-length-2198-cov-1.824140",
      "start": 931,
      "end": 2196,
      "strand": "-"
    }
  ]
}

The sequence value is abbreviated above for readability.

Use cases

The examples below use Python and the requests library. Each one reuses the BASE address defined in the first example.

Tip

These examples can be edited and run in your browser, without installing anything, on the MGnify Proteins API in Python page.

Look up a protein and extract its sequence

import requests

BASE = "https://www.ebi.ac.uk/metagenomics/proteins/api/v1"

protein = requests.get(f"{BASE}/protein/MGYP000261684433").json()

print(protein["sequence"])
EESGVTRAVQGAGDEVPGEVFFEKGVVEETLRGGPAGEAAAGDTEAATAETDDGHLGSVGRNEKTSFAELKAEYESGDLEWVDDEDRETGPDTGESEHSKTSFADLKAEYESGDLEWVDDEGPDEAAARTTGSGDERTAASVETATTEVVPGEEERTAGEADEGEWDEGEWDGGEGDEETGDLADELDELELFEDEIEWDGDDNTPEESLARAGEEAGEREAERAAEDERTVEDERAAEDERGVSRDATGADTATAEEDSSADAPTADQRPDDAAGSRGQEGEAPSPEAASTSAGESPSADREGVEPEAASGGATKRRPPGESGEGKPYLETLPQGHWADLLVMEWLEFLVEEGGTQAATRALEYYERIGWIDGGVTEELERYLAGFEGDGDGALSIDHHRRSLSYVDQLGDGDVSVERLL

The same record written out as FASTA:

print(f">{protein['mgyp']}\n{protein['sequence']}")
>MGYP000261684433
EESGVTRAVQGAGDEVPGEVFFEKGVVEETLRGGPAGEAAAGDTEAATAETDDGHLGSVGRNEKTSFAELKAEYESGDLEWVDDEDRETGPDTGESEHSKTSFADLKAEYESGDLEWVDDEGPDEAAARTTGSGDERTAASVETATTEVVPGEEERTAGEADEGEWDEGEWDGGEGDEETGDLADELDELELFEDEIEWDGDDNTPEESLARAGEEAGEREAERAAEDERTVEDERAAEDERGVSRDATGADTATAEEDSSADAPTADQRPDDAAGSRGQEGEAPSPEAASTSAGESPSADREGVEPEAASGGATKRRPPGESGEGKPYLETLPQGHWADLLVMEWLEFLVEEGGTQAATRALEYYERIGWIDGGVTEELERYLAGFEGDGDGALSIDHHRRSLSYVDQLGDGDVSVERLL

Building a FASTA file for a biome

A common workflow: find the cluster representatives observed in a biome, then retrieve each sequence. The search endpoint returns the accessions, and the detail endpoint turns each one into a sequence.

import requests

BASE = "https://www.ebi.ac.uk/metagenomics/proteins/api/v1"

# 1. Find cluster representatives from this biome and all of its sub-biomes.
hits = requests.get(
    f"{BASE}/protein/search",
    params={"biome_lineage": "root:Engineered:Wastewater", "limit": 10},
).json()

# 2. Fetch each protein, and write it out as FASTA.
with open("wastewater.fasta", "w") as fasta_file:
    for hit in hits:
        protein = requests.get(f"{BASE}/protein/{hit['mgyp']}").json()
        fasta_file.write(f">{protein['mgyp']}\n{protein['sequence']}\n")

print(f"Wrote {len(hits)} sequences to wastewater.fasta")
Note

requests encodes the query parameters, so biome names that contain spaces — for example root:Host-associated:Human:Digestive system — need no special handling.

Tip

This makes one request per protein, so keep limit modest and be considerate of the service. This service is rate-limited, so queries are going to be throttled. For thousands of sequences, download the release from the FTP server instead.

Finding proteins that carry a Pfam domain

Search by Pfam accession to get the matching accessions:

hits = requests.get(
    f"{BASE}/protein/search",
    params={"pfam_accession": "PF00005", "limit": 5},
).json()

for hit in hits:
    print(hit["mgyp"])
MGYP000000000166
MGYP000000000617
MGYP000000002016
MGYP000000005958
MGYP000000006630

Fetching each hit from the detail endpoint adds the sequence length and the domains it carries:

for hit in hits:
    protein = requests.get(f"{BASE}/protein/{hit['mgyp']}").json()
    domains = ", ".join(p["accession"] for p in protein["pfam_annotations"])
    length = "full-length" if protein["full_length"] else "fragment"
    print(f"{protein['mgyp']}\t{length}\t{len(protein['sequence'])} aa\t{domains}")

Exploring outwards from one protein

The biome ids in a detail response are the same ids the search endpoint accepts, so you can start from a protein of interest and find others sharing its biome:

protein = requests.get(f"{BASE}/protein/MGYP000261684433").json()

for biome in protein["biomes"]:
    print(biome["id"], biome["name"])
132 root:Environmental:Aquatic:Marine
neighbours = requests.get(
    f"{BASE}/protein/search",
    params={"biome_id": protein["biomes"][0]["id"], "limit": 10},
).json()

for hit in neighbours:
    print(hit["mgyp"])
MGYP000000000012
MGYP000000000101
MGYP000000000348
MGYP000000000812
MGYP000000000829
MGYP000000000853
MGYP000000000871
MGYP000000000872
MGYP000000001138
MGYP000000001467

License

The data is available for both academic and commercial use under a CC0 1.0 Universal License.

If you make use of the MGnify Protein Database, please cite the following paper:

  • Richardson, L., Allen, B., Baldi, G., Beracochea, M., Bileschi, M. L., Burdett, T., Burgin, J., Caballero-Pérez, J., Cochrane, G., Colwell, L. J., Curtis, T., Escobar-Zepeda, A., Gurbich, T. A., Kale, V., Korobeynikov, A., Raj, S., Rogers, A. B., Sakharova, E., Sanchez, S., Wilkinson, D. J., Finn, R. D. MGnify: the microbiome sequence data analysis resource in 2023. Nucleic Acids Research (2023). https://doi.org/10.1093/nar/gkac1080

Citation

BibTeX citation:
@online{2026,
  author = {, MGnify},
  title = {Proteins {API}},
  date = {2026-09-23},
  url = {https://docs.mgnify.org/src/docs/mgnify-proteins-api.html},
  langid = {en}
}
For attribution, please cite this work as:
MGnify. 2026. “Proteins API.” September 23. https://docs.mgnify.org/src/docs/mgnify-proteins-api.html.