
Jaspar Database
- 1.2k installs
- 2.6k repo stars
- Updated July 7, 2026
- google-deepmind/science-skills
jaspar-database is a Python agent skill that queries the JASPAR transcription factor binding profile database via API for developers who need programmatic motif and TFBS lookups in genomics pipelines.
About
jaspar-database is a Google DeepMind science-skills wrapper around the JASPAR API for AI coding agents. The skill ships as a Python ≥3.10 script module that depends on scienceskillscommon and exposes transcription factor binding profile queries without leaving the agent session. Developers reach for jaspar-database when building or extending genomics, regulatory genomics, or motif-analysis code that must fetch curated PWM/profile data from JASPAR instead of hard-coding matrices or scraping the web UI. The README positions it explicitly as a JASPAR API skill wrapper under Apache 2.0, making it suitable for reproducible bioinformatics automation inside Claude Code, Cursor, or Codex workflows.
- Wraps the official JASPAR REST API (https://jaspar.elixir.no/api/v1/) with rate-limited HTTP client
- Supports all official output formats: json, jsonp, jaspar, meme, transfac, pfm, yaml
- Automatic output truncation at 50,000 characters with clear continuation notice
- Built on scienceskillscommon with shared HTTP utilities and 10 QPS throttling
- Ready-to-use argparse CLI for interactive and scripted database queries
Jaspar Database by the numbers
- 1,246 all-time installs (skills.sh)
- +166 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #917 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/google-deepmind/science-skills --skill jaspar-databaseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.2k |
|---|---|
| repo stars | ★ 2.6k |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 7, 2026 |
| Repository | google-deepmind/science-skills ↗ |
How do you query JASPAR TF binding profiles from code?
Query the JASPAR transcription factor binding profile database directly from their AI coding agent.
Who is it for?
Bioinformatics and computational biology developers wiring JASPAR motif data into Python pipelines, notebooks, or agent-driven analysis scripts.
Skip if: Developers who only need general-purpose REST clients or who are not working with transcription factor binding sites and regulatory genomics data.
When should I use this skill?
The user mentions JASPAR, transcription factor binding profiles, PWM matrices, TFBS lookup, or motif databases in genomics code.
What you get
Programmatic JASPAR API query results, PWM/profile metadata, and agent-ready binding-site lookup outputs for downstream analysis code.
- JASPAR API query results
- TF binding profile metadata
By the numbers
- Requires Python ≥3.10
- Depends on scienceskillscommon package
Files
JASPAR Skill
JASPAR is the definitive open-access database for Transcription Factor (TF) binding profiles, stored as Position Frequency Matrices (PFMs).
Use this skill to map abstract sequence motifs or genomic regions to specific biological regulators (e.g., "what TFs bind here?" or "what is the motif for CTCF?").
Prerequisites
1. `uv`: Read the uv skill and follow its Setup instructions to ensure uv is installed and on PATH. 2. User Notification: If LICENSE_NOTIFICATION.txt does not already exist in this skill directory then (1) prominently notify the user to check the terms at https://jaspar.elixir.no/ and https://jaspar.elixir.no/api/, then (2) create the file recording the notification text and timestamp.
Core Rules
CRITICAL: You MUST respect the JASPAR API Terms of Use by adhering to the following:
- Use the Wrapper: ALWAYS execute the provided helper scripts to query the
database rather than accessing the database directly. The scripts automatically enforce the required rate limit gracefully.
- Maximum API Window Size: The genomic window for a single API query MUST
NOT exceed 100,000 bp (100kb). The jaspar_api.py script automatically chunks larger requests for you to bypass this limitation when querying larger regions.
- Valid Matrix IDs:
get_tf_motif,get_tf_metadata, andget_tf_pwm
require a stable JASPAR Matrix ID (e.g., MA0488.2). If a user provides a gene symbol (e.g., JUN), you must resolve it first using resolve_tf_id.
- Taxonomy Required: Resolving IDs requires a
tax_idto ensure targeted
searches. Common IDs: Human=9606, Mouse=10090.
- Notification: If this skill is used, ensure this is mentioned in the
output.
Utility Scripts
Run all commands using the bundled Python script:
1. Resolve TF to Matrix ID
Maps a transcription factor name to a stable Matrix ID. Required step before fetching motifs if only a gene name is provided.
uv run scripts/jaspar_api.py resolve_tf_id --name "JUN" --tax-id 96062. Get TF Motif (PFM)
Retrieves the raw Position Frequency Matrix for a specific TF. Supports --format flag.
uv run scripts/jaspar_api.py get_tf_motif --matrix-id "MA0488.2"
uv run scripts/jaspar_api.py get_tf_motif --matrix-id "MA0488.2" --format meme3. Get TF Metadata
Retrieves TF class, family, and links to external databases (e.g., UniProt). Supports --format flag.
uv run scripts/jaspar_api.py get_tf_metadata --matrix-id "MA0488.2"
uv run scripts/jaspar_api.py get_tf_metadata --matrix-id "MA0488.2" --format yaml4. Compute PWM (Position Weight Matrix)
Fetches the PFM for a matrix and converts it to log-odds scores (PWM).
uv run scripts/jaspar_api.py get_tf_pwm --matrix-id "MA0488.2"
uv run scripts/jaspar_api.py get_tf_pwm --matrix-id "MA0488.2" --pseudocount 0.15. Infer Matrix from Protein Sequence
Infers potential JASPAR matrix profiles from a raw transcription factor protein sequence.
uv run scripts/jaspar_api.py infer_from_sequence --sequence "QAQLLPSHHVG"6. Get TF Flexible Model (TFFM)
Retrieves metadata for a JASPAR TF Flexible Model. (Note: The JASPAR TFFM endpoints occasionally experience 500 Internal Server errors).
uv run scripts/jaspar_api.py get_tffm --tffm-id "TFFM0001.1"Output Formats
The get_tf_motif and get_tf_metadata commands accept an optional --format flag. Supported formats: json (default), jsonp, jaspar, meme, transfac, pfm, yaml.
Anti-Patterns
- DON'T pass gene symbols (e.g.,
JUN) toget_tf_motif. You must pass
the MA... Matrix ID.
- DON'T forget the
--tax-idwhen resolving a TF name. - DON'T use this skill for determining tissue-specific epigenetic
availability (JASPAR shows potential binding, not actual tissue expression context).
- DON'T use this skill to model how a specific protein mutation affects
binding.
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""JASPAR API skill wrapper."""
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "scienceskillscommon",
# ]
# [tool.uv.sources]
# scienceskillscommon = { path = "../../scienceskillscommon" }
# ///
import argparse
import math
import re
import sys
import urllib.parse
import urllib.request
from science_skills.skills.scienceskillscommon import http_client
JASPAR_URL = "https://jaspar.elixir.no/api/v1/"
_CLIENT = http_client.HttpClient(JASPAR_URL, qps=10)
_MAX_OUTPUT_CHARS = 50_000
def _print_text(text):
"""Prints text, truncating if it exceeds _MAX_OUTPUT_CHARS."""
if len(text) > _MAX_OUTPUT_CHARS:
print(text[:_MAX_OUTPUT_CHARS])
print(
f"\n... [truncated: {len(text)} chars"
f" total, showing first {_MAX_OUTPUT_CHARS}]"
)
else:
print(text)
_VALID_FORMATS = (
"json",
"jsonp",
"jaspar",
"meme",
"transfac",
"pfm",
"yaml",
)
def validate_matrix_id(matrix_id: str):
"""Validates the format of a JASPAR Matrix ID."""
if not re.match(r"^MA\d{4}\.\d+$", matrix_id):
print(
f"Error: Invalid Matrix ID format '{matrix_id}'. Expected format is"
" 'MA0488.2'.",
file=sys.stderr,
)
print(
"Hint: If you have a gene symbol (e.g., 'JUN'), you must first use the"
" 'resolve_tf_id' command.",
file=sys.stderr,
)
sys.exit(1)
def resolve_tf_id(name: str, tax_id: str):
"""Resolves a TF name to a JASPAR Matrix ID."""
url = f"{JASPAR_URL}matrix/?name={urllib.parse.quote(name)}&tax_id={tax_id}"
print("Request url: ", url)
data = _CLIENT.fetch_json(url)
if not data or "results" not in data or len(data["results"]) == 0:
print(f"No results found for TF '{name}' in tax_id {tax_id}")
return
print(
f"Found {len(data['results'])} matching Matrix IDs for '{name}' (tax_id:"
f" {tax_id}):\n"
)
for r in data["results"]:
matrix_id = r.get("matrix_id")
tf_name = r.get("name")
family = r.get("family", [])
species = r.get("species", [])
family_str = ", ".join(family) if isinstance(family, list) else family
species_str = (
", ".join([str(s.get("tax_id")) for s in species])
if species
else "Unknown"
)
print(f"- Matrix ID: {matrix_id}")
print(f" Name: {tf_name}")
print(f" Family: {family_str}")
print(f" Taxonomies: {species_str}\n")
def infer_from_sequence(sequence):
"""Infers potential TF binding matrices from a raw protein sequence."""
url = f"{JASPAR_URL}infer/{urllib.parse.quote(sequence)}/"
print("Request url: ", url)
data = _CLIENT.fetch_json(url)
if not data or "results" not in data or not data["results"]:
print("No corresponding matrices inferred from sequence.")
return
print(f"Inferred {len(data['results'])} potential TF profiles:")
for r in data["results"]:
mid = r.get("matrix_id")
name = r.get("name")
print(f"- {mid} ({name}): E-value {r.get('evalue')}")
def get_tffm(tffm_id):
"""Gets TF Flexible Model (TFFM) detail information."""
url = f"{JASPAR_URL}tffm/{urllib.parse.quote(tffm_id)}/"
print("Request url: ", url)
data = _CLIENT.fetch_json(url)
print(dict_to_yaml(data))
def get_tf_motif(matrix_id, fmt="json"):
"""Gets the Position Frequency Matrix (PFM) for a specific TF."""
validate_matrix_id(matrix_id)
url = f"{JASPAR_URL}matrix/{matrix_id}/"
if fmt != "json":
url += f"?format={fmt}"
print("Request url: ", url)
_print_text(_CLIENT.fetch_text(url))
return
print("Request url: ", url)
data = _CLIENT.fetch_json(url)
print(f"Matrix ID: {data.get('matrix_id')}")
print(f"Name: {data.get('name')}")
print("PFM:")
pfm = data.get("pfm", {})
for base in ["A", "C", "G", "T"]:
if base in pfm:
vals = " ".join([str(x) for x in pfm[base]])
print(f"{base} [ {vals} ]")
def get_tf_metadata(matrix_id, fmt="json"):
"""Gets metadata for a specific TF."""
validate_matrix_id(matrix_id)
url = f"{JASPAR_URL}matrix/{matrix_id}/"
if fmt != "json":
url += f"?format={fmt}"
print("Request url: ", url)
_print_text(_CLIENT.fetch_text(url))
return
print("Request url: ", url)
data = _CLIENT.fetch_json(url)
print(dict_to_yaml(data))
def get_tf_pwm(matrix_id, pseudocount=0.8):
"""Computes a Position Weight Matrix (PWM) from a PFM.
Fetches the raw PFM for the given matrix ID and converts it to log-odds
scores (in bits) using the standard two-step conversion:
1. PPM[b][i] = (PFM[b][i] + pseudocount) / (N_i + 4 * pseudocount)
2. PWM[b][i] = log2( PPM[b][i] / background[b] )
where N_i is the total count at position i and background is uniform (0.25).
The --pseudocount flag is a *per-base* pseudocount (default 0.8). This is
equivalent to a total pseudocount B = 4 * pseudocount = 3.2 in the textbook
formulation: PPM[b][i] = (count + B * p_bg) / (N + B), with uniform p_bg.
Args:
matrix_id: The JASPAR Matrix ID.
pseudocount: The per-base pseudocount to use (default 0.8).
"""
validate_matrix_id(matrix_id)
url = f"{JASPAR_URL}matrix/{matrix_id}/"
print("Request url: ", url)
data = _CLIENT.fetch_json(url)
pfm = data.get("pfm", {})
if not pfm:
print(f"Error: No PFM data found for {matrix_id}.", file=sys.stderr)
sys.exit(1)
bases = ["A", "C", "G", "T"]
num_positions = len(pfm.get("A", []))
background = 0.25
print(f"Matrix ID: {data.get('matrix_id')}")
print(f"Name: {data.get('name')}")
print(f"Pseudocount: {pseudocount}")
print(f"Background: {background} (uniform)")
print(f"Positions: {num_positions}")
print("PWM (log2 odds):")
for base in bases:
if base not in pfm:
continue
scores = []
for i in range(num_positions):
n_i = sum(pfm[b][i] for b in bases if b in pfm)
freq = (pfm[base][i] + pseudocount) / (n_i + 4 * pseudocount)
score = math.log2(freq / background)
scores.append(f"{score:+.4f}")
print(f"{base} [ {' '.join(scores)} ]")
def dict_to_yaml(d, indent=0):
"""Converts a dictionary to a YAML-like string."""
res = ""
for k, v in d.items():
if isinstance(v, dict):
res += f"{' ' * indent}{k}:\n{dict_to_yaml(v, indent + 2)}"
elif isinstance(v, list):
res += f"{' ' * indent}{k}: {', '.join([str(x) for x in v])}\n"
else:
res += f"{' ' * indent}{k}: {v}\n"
return res
def main():
parser = argparse.ArgumentParser(description="JASPAR API wrapper skill")
subparsers = parser.add_subparsers(dest="command", required=True)
# resolve_tf_id
p_res = subparsers.add_parser("resolve_tf_id")
p_res.add_argument("--name", required=True)
p_res.add_argument("--tax-id", required=True, type=int)
# get_tf_motif
p_mot = subparsers.add_parser("get_tf_motif")
p_mot.add_argument("--matrix-id", required=True)
p_mot.add_argument(
"--format",
default="json",
choices=_VALID_FORMATS,
help="Output format (default: json)",
)
# get_tf_metadata
p_meta = subparsers.add_parser("get_tf_metadata")
p_meta.add_argument("--matrix-id", required=True)
p_meta.add_argument(
"--format",
default="json",
choices=_VALID_FORMATS,
help="Output format (default: json)",
)
# get_tf_pwm
p_pwm = subparsers.add_parser("get_tf_pwm")
p_pwm.add_argument("--matrix-id", required=True)
p_pwm.add_argument(
"--pseudocount",
type=float,
default=0.8,
help="Pseudocount for PWM computation (default: 0.8)",
)
# infer_from_sequence
p_inf = subparsers.add_parser("infer_from_sequence")
p_inf.add_argument("--sequence", required=True, help="Raw protein sequence")
# get_tffm
p_tffm = subparsers.add_parser("get_tffm")
p_tffm.add_argument("--tffm-id", required=True)
args = parser.parse_args()
if args.command == "resolve_tf_id":
resolve_tf_id(args.name, args.tax_id)
elif args.command == "get_tf_motif":
get_tf_motif(args.matrix_id, fmt=args.format)
elif args.command == "get_tf_metadata":
get_tf_metadata(args.matrix_id, fmt=args.format)
elif args.command == "get_tf_pwm":
get_tf_pwm(args.matrix_id, pseudocount=args.pseudocount)
elif args.command == "infer_from_sequence":
infer_from_sequence(args.sequence)
elif args.command == "get_tffm":
get_tffm(args.tffm_id)
if __name__ == "__main__":
main()
Related skills
FAQ
What does jaspar-database query?
jaspar-database queries the JASPAR transcription factor binding profile database through its API wrapper. Developers use the skill from an AI coding agent to retrieve curated PWM and binding-site profile data for genomics and motif-analysis code.
What are jaspar-database prerequisites?
jaspar-database requires Python 3.10 or newer and the scienceskillscommon package listed in its script metadata. The skill is distributed as part of google-deepmind/science-skills under Apache 2.0.
Is Jaspar Database safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.