Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Metaculus/metaculus/llms.txt

Use this file to discover all available pages before exploring further.

This guide demonstrates how to retrieve questions from the Metaculus API using various filters and pagination.

Basic Query

Retrieve a feed of posts (which contain questions):
import requests

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

# Get posts feed
response = requests.get(
    "https://www.metaculus.com/api/posts/",
    headers=headers
)

data = response.json()
print(f"Total posts: {len(data['results'])}")
print(f"Next page: {data['next']}")

for post in data['results']:
    print(f"Post {post['id']}: {post['title']}")
    if post.get('question'):
        print(f"  Question type: {post['question']['type']}")

Filtering by Question Type

Filter posts by the type of question they contain:
import requests

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

# Get only binary questions
params = {
    "forecast_type": ["binary"],
    "limit": 20
}

response = requests.get(
    "https://www.metaculus.com/api/posts/",
    headers=headers,
    params=params
)

data = response.json()
for post in data['results']:
    question = post.get('question')
    if question:
        print(f"{question['title']}")
        print(f"  Status: {question['status']}")
        print(f"  Open time: {question['open_time']}")
        print()

Available Question Types

  • binary - Yes/no questions
  • multiple_choice - Questions with multiple options
  • numeric - Continuous numeric predictions
  • date - Date predictions
  • conditional - Conditional question pairs
  • group_of_questions - Multiple related sub-questions

Filtering by Status

Get questions based on their lifecycle status:
import requests

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

# Get only open questions
params = {
    "statuses": ["open"],
    "forecast_type": ["numeric"],
    "limit": 10
}

response = requests.get(
    "https://www.metaculus.com/api/posts/",
    headers=headers,
    params=params
)

data = response.json()
print(f"Found {len(data['results'])} open numeric questions")

for post in data['results']:
    question = post.get('question')
    if question:
        print(f"\nQuestion ID: {question['id']}")
        print(f"Title: {question['title']}")
        print(f"Close time: {question['scheduled_close_time']}")
        print(f"Range: {question['scaling']['range_min']} to {question['scaling']['range_max']}")

Available Statuses

  • upcoming - Not yet open for forecasting
  • open - Currently accepting forecasts
  • closed - No longer accepting forecasts
  • resolved - Question has been resolved

Filtering by Tournament

Get questions from specific tournaments or projects:
import requests

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

# Get questions from specific tournaments
params = {
    "tournaments": ["ai-forecasting", "metaculus-cup"],
    "statuses": ["open"],
    "limit": 20
}

response = requests.get(
    "https://www.metaculus.com/api/posts/",
    headers=headers,
    params=params
)

data = response.json()
for post in data['results']:
    print(f"Post: {post['title']}")
    # Show which tournaments this post belongs to
    if post.get('projects', {}).get('tournament'):
        tournaments = [t['name'] for t in post['projects']['tournament']]
        print(f"  Tournaments: {', '.join(tournaments)}")
    print()

Filtering by Category

Filter questions by topic categories:
import requests

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

# Get questions from specific categories
params = {
    "categories": ["nuclear", "health-pandemics"],
    "statuses": ["open"],
    "limit": 15
}

response = requests.get(
    "https://www.metaculus.com/api/posts/",
    headers=headers,
    params=params
)

data = response.json()
for post in data['results']:
    print(f"\n{post['title']}")
    if post.get('projects', {}).get('category'):
        categories = [c['name'] for c in post['projects']['category']]
        print(f"Categories: {', '.join(categories)}")

Filtering by Date Range

Get questions that opened, close, or resolve within specific date ranges:
import requests
from datetime import datetime, timedelta

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

# Get questions that opened in the last 7 days
week_ago = (datetime.now() - timedelta(days=7)).isoformat()
params = {
    "open_time__gte": week_ago,
    "statuses": ["open"],
    "limit": 20,
    "order_by": "-open_time"  # Most recent first
}

response = requests.get(
    "https://www.metaculus.com/api/posts/",
    headers=headers,
    params=params
)

data = response.json()
print(f"Found {len(data['results'])} questions opened in the last week\n")

for post in data['results']:
    question = post.get('question')
    if question:
        print(f"{question['title']}")
        print(f"  Opened: {question['open_time']}")
        print(f"  Type: {question['type']}")
        print()

Available Date Filters

Each filter supports these operators:
  • __gt - Greater than
  • __gte - Greater than or equal to
  • __lt - Less than
  • __lte - Less than or equal to
Date filter fields:
  • open_time - When the question opened for forecasting
  • published_at - When the post was published
  • scheduled_resolve_time - When the question is scheduled to resolve

Pagination

Handle large result sets with pagination:
import requests

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

def fetch_all_pages(initial_url, max_pages=5):
    """Fetch multiple pages of results"""
    all_posts = []
    url = initial_url
    page = 0
    
    while url and page < max_pages:
        response = requests.get(url, headers=headers)
        data = response.json()
        
        all_posts.extend(data['results'])
        url = data.get('next')  # URL for next page
        page += 1
        
        print(f"Fetched page {page}, total posts: {len(all_posts)}")
    
    return all_posts

# Fetch first 5 pages of binary questions
params = {
    "forecast_type": ["binary"],
    "statuses": ["open"],
    "limit": 20,
    "offset": 0
}

base_url = "https://www.metaculus.com/api/posts/"
first_url = f"{base_url}?" + "&".join([f"{k}={v}" for k, v in params.items()])

posts = fetch_all_pages(first_url)
print(f"\nTotal posts fetched: {len(posts)}")

Sorting Results

Order results by different criteria:
import requests

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

# Get most commented questions
params = {
    "statuses": ["open"],
    "order_by": "-comment_count",  # Prefix with - for descending
    "limit": 10
}

response = requests.get(
    "https://www.metaculus.com/api/posts/",
    headers=headers,
    params=params
)

data = response.json()
print("Most discussed questions:\n")

for post in data['results']:
    print(f"{post['title']}")
    print(f"  Comments: {post['comment_count']}")
    print(f"  Forecasters: {post['nr_forecasters']}")
    print()

Available Sort Options

  • published_at - Publication date
  • open_time - When question opened
  • vote_score - Community votes
  • comment_count - Number of comments
  • forecasts_count - Number of forecasts
  • scheduled_close_time - Close date
  • scheduled_resolve_time - Resolution date
  • hotness - Composite popularity score
  • weekly_movement - Recent forecast changes
  • divergence - Disagreement among forecasters
Prefix with - for descending order (e.g., -published_at).

Getting a Single Post

Retrieve detailed information about a specific post:
import requests

API_TOKEN = "your_api_token_here"
headers = {"Authorization": f"Token {API_TOKEN}"}

# Get specific post by ID
post_id = 3530
response = requests.get(
    f"https://www.metaculus.com/api/posts/{post_id}/",
    headers=headers
)

post = response.json()
print(f"Title: {post['title']}")
print(f"Status: {post['status']}")
print(f"Forecasters: {post['nr_forecasters']}")
print(f"Comments: {post['comment_count']}")

if post.get('question'):
    question = post['question']
    print(f"\nQuestion Details:")
    print(f"  Type: {question['type']}")
    print(f"  ID: {question['id']}")
    print(f"  Open: {question['open_time']}")
    print(f"  Close: {question['scheduled_close_time']}")
    
    if question['type'] in ['numeric', 'date']:
        print(f"  Range: {question['scaling']['range_min']} to {question['scaling']['range_max']}")
        print(f"  Open bounds: lower={question['open_lower_bound']}, upper={question['open_upper_bound']}")

Next Steps