Skip to main content
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

Build docs developers (and LLMs) love