ft APIft.com ↗
Search and retrieve FT commodities news articles. Filter by date range, keyword, and sort order. Access curated topic pages for oil, gold, copper, and more.
What is the ft API?
The Financial Times Commodities API exposes 2 endpoints for retrieving market news from ft.com, covering topics from oil and gold to agricultural commodities and industrial metals. The search_news endpoint accepts keyword queries with date range filters and returns up to 25 articles per page, each with title, URL, topic tag, summary, and publication date. The get_topic_articles endpoint retrieves editorially curated articles from named FT topic pages.
curl -X GET 'https://api.parse.bot/scraper/0e37e2f1-5dc3-4915-956f-b8f461f1ae07/search_news' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace ft-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""
Financial Times Commodities News API Client
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from datetime import datetime, timedelta
class ParseClient:
"""Client for the Financial Times Commodities News API via Parse Bot."""
def __init__(self, api_key: str = None):
"""Initialize the Parse API client.
Args:
api_key: API key for Parse Bot. If not provided, reads from PARSE_API_KEY env var.
"""
self.base_url = "https://api.parse.bot"
self.scraper_id = "0e37e2f1-5dc3-4915-956f-b8f461f1ae07"
self.api_key = api_key or os.getenv("PARSE_API_KEY")
if not self.api_key:
raise ValueError("API key is required. Set PARSE_API_KEY environment variable or pass api_key parameter.")
def _call(self, endpoint: str, method: str = "POST", **params) -> dict:
"""Make an API call to the Parse Bot scraper.
Args:
endpoint: The endpoint name (e.g., 'search_news', 'get_topic_articles')
method: HTTP method - 'GET' or 'POST'
**params: Query or body parameters depending on method
Returns:
dict: JSON response from the API
"""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
if method.upper() == "GET":
response = requests.get(url, headers=headers, params=params)
elif method.upper() == "POST":
response = requests.post(url, headers=headers, json=params)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
return response.json()
def search_news(
self,
query: str = "commodities",
sort: str = "date",
page: int = 1,
date_from: str = None,
date_to: str = None
) -> dict:
"""Search Financial Times articles by keyword.
Args:
query: Search query string (e.g., 'commodities', 'oil prices')
sort: Sort order - 'date' or 'relevance'
page: Page number for pagination, starting from 1
date_from: Start date in YYYY-MM-DD format
date_to: End date in YYYY-MM-DD format
Returns:
dict: Search results with articles, total count, and pagination info
"""
params = {
"query": query,
"sort": sort,
"page": str(page)
}
if date_from:
params["date_from"] = date_from
if date_to:
params["date_to"] = date_to
return self._call("search_news", method="GET", **params)
def get_topic_articles(self, topic: str = "commodities") -> dict:
"""Get the latest curated articles from an FT topic page.
Args:
topic: FT topic page slug (e.g., 'commodities', 'oil', 'gold', 'copper')
Returns:
dict: Topic articles with article count and details
"""
return self._call("get_topic_articles", method="GET", topic=topic)
def main():
"""Practical workflow example: monitor commodity markets and track trends."""
# Initialize the API client
client = ParseClient()
print("=" * 80)
print("Financial Times Commodities Market Intelligence")
print("=" * 80)
print()
# Workflow: Monitor multiple commodity topics and analyze recent coverage
commodity_topics = ["commodities", "oil", "gold"]
all_articles = []
print("Step 1: Fetching latest curated articles from key commodity topics...")
print("-" * 80)
for topic in commodity_topics:
print(f"\n📊 Checking {topic.upper()} topic page...")
topic_data = client.get_topic_articles(topic=topic)
print(f" Found {topic_data['article_count']} articles")
# Display first 3 articles from each topic
for i, article in enumerate(topic_data['articles'][:3], 1):
print(f" {i}. {article['title']}")
print(f" Topic: {article['topic']}")
if article['summary']:
print(f" Summary: {article['summary'][:60]}...")
all_articles.append(article)
print("\n" + "=" * 80)
print("Step 2: Searching for recent oil price articles (last 30 days)...")
print("-" * 80)
# Calculate date range for last 30 days
end_date = datetime.now()
start_date = end_date - timedelta(days=30)
date_from = start_date.strftime("%Y-%m-%d")
date_to = end_date.strftime("%Y-%m-%d")
search_results = client.search_news(
query="oil prices",
sort="date",
page=1,
date_from=date_from,
date_to=date_to
)
print(f"\nSearch Query: 'oil prices'")
print(f"Date Range: {date_from} to {date_to}")
print(f"Total Results Found: {search_results['total_results']}")
print(f"Results on Current Page: {len(search_results['articles'])}")
print()
# Display search results
for i, article in enumerate(search_results['articles'][:5], 1):
pub_date = article['published_date']
if pub_date:
pub_date = datetime.fromisoformat(pub_date.replace('Z', '+00:00')).strftime("%Y-%m-%d %H:%M")
print(f"{i}. {article['title']}")
print(f" Published: {pub_date}")
print(f" Topic: {article['topic']}")
print(f" URL: {article['url']}")
print()
print("=" * 80)
print("Step 3: Searching for metals market trends...")
print("-" * 80)
# Search for metals-related articles sorted by relevance
metals_search = client.search_news(
query="copper gold metals market",
sort="relevance",
page=1
)
print(f"\nSearch Query: 'copper gold metals market'")
print(f"Sort Order: relevance")
print(f"Total Results Found: {metals_search['total_results']}")
print()
# Analyze the results
topic_distribution = {}
for article in metals_search['articles'][:10]:
topic = article['topic']
topic_distribution[topic] = topic_distribution.get(topic, 0) + 1
print("Topic Distribution in Results:")
for topic, count in sorted(topic_distribution.items(), key=lambda x: x[1], reverse=True):
print(f" • {topic}: {count} articles")
print("\n" + "=" * 80)
print("Summary:")
print(f" • Total articles reviewed: {len(all_articles) + len(search_results['articles']) + len(metals_search['articles'])}")
print(f" • Topics monitored: {', '.join(commodity_topics)}")
print(f" • Search queries executed: 2 (oil prices, metals)")
print("=" * 80)
if __name__ == "__main__":
main()Search Financial Times articles by keyword with optional date range filtering and sort order. Returns paginated results with 25 articles per page. Results include article title, URL, topic tag, summary, and publication date.
| Param | Type | Description |
|---|---|---|
| page | string | Page number for pagination, starting from 1. |
| sort | string | Sort order for results. Accepts exactly one of: date, relevance. |
| query | string | Search query string (e.g. 'commodities', 'oil prices', 'gold market'). |
| date_to | string | End date filter in YYYY-MM-DD format. When omitted, no end date constraint is applied. |
| date_from | string | Start date filter in YYYY-MM-DD format. When omitted, no start date constraint is applied. |
{
"type": "object",
"fields": {
"page": "integer",
"sort": "string",
"query": "string",
"articles": "array of article objects with title, url, topic, summary, published_date",
"total_results": "integer"
},
"sample": {
"page": 1,
"sort": "date",
"query": "commodities",
"articles": [
{
"url": "https://www.ft.com/content/c49e0eff-0776-4103-8eaf-1b049fbf9d3f",
"title": "Apollo and Blackstone raise $35bn in chip financing deal for Anthropic",
"topic": "Artificial intelligence",
"summary": "Transaction is one of the largest private credit fundraisings, fuelling Claude maker's AI growth plans",
"published_date": "2026-06-10T16:18:18+0000"
}
],
"total_results": 205
}
}About the ft API
What the API Returns
Both endpoints return article arrays containing title, url, topic, summary, and published_date fields. The search_news endpoint also surfaces total_results and the active page and sort values so you can paginate through large result sets. Each page of search results contains up to 25 articles.
search_news Endpoint
The search_news endpoint accepts a query string (e.g. 'oil prices', 'gold market', 'copper supply') alongside optional date_from and date_to parameters in YYYY-MM-DD format to narrow results to a specific window. The sort parameter accepts either date or relevance, letting you choose between chronological ordering and query match strength. Pagination is controlled via the page parameter starting from 1.
get_topic_articles Endpoint
The get_topic_articles endpoint takes a topic slug — such as 'commodities', 'oil', 'gold', 'copper', or 'agricultural-commodities' — and returns the curated article list for that FT topic page. The response includes an article_count field alongside the articles array. Note that articles from topic pages are editorially curated and may not always include a published_date value.
Coverage and Scope
The API is focused on the FT commodities vertical. It does not expose FT content outside commodities topics, nor does it provide full article body text — only the summary, title, URL, and metadata fields listed above. If you need to track a specific commodity over time, combining date_from/date_to filtering in search_news with a targeted query value gives you a reliable time-bounded dataset.
The ft API is a managed, monitored endpoint for ft.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when ft.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official ft.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Monitor FT coverage of oil price movements by querying 'oil prices' with a rolling date window using date_from and date_to.
- Build a commodities news feed grouped by topic using get_topic_articles with slugs like 'gold', 'copper', and 'agricultural-commodities'.
- Track how FT editorial attention to a commodity shifts over time by comparing total_results across different date ranges.
- Aggregate article summaries and URLs for a commodities briefing digest using search_news sorted by date.
- Alert on new FT articles mentioning a specific commodity or event by polling search_news with a tight date_from filter.
- Compare coverage frequency of industrial metals vs. agricultural commodities using separate topic page requests.
- Archive FT commodities headlines with publication dates for historical market sentiment research.
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.