Fetching Ghost Content with the Built-in Content API: A Practical Guide
Learn how to fetch published posts from Ghost using the built-in Content API, with working JavaScript examples, filtering, pagination, and key limitations to watch for.
23 Jan 2026, 19:07 UTC

The Problem: Getting Blog Content into Your Frontend App
When you need to pull published posts from a Ghost blog into a custom frontend—whether it's a React app, a mobile client, or a static site generator—you need a reliable way to access that content programmatically. Ghost's built-in Content API gives you that capability without requiring custom endpoints or database access.
Understanding the Content API Structure
The Content API is a REST endpoint available at /ghost/api/content/ on any Ghost 1.0+ installation. It uses a public API key for authentication, which you can generate in Ghost Admin under Integrations. Unlike the Admin API, the Content API only exposes published content, making it safe to expose in client-side applications.
Key endpoints include:
/content/posts– Retrieve published posts/content/pages– Retrieve published pages/content/authors– Retrieve author data/content/tags– Retrieve tag data
Getting Started with a Basic Request
Every request requires your key parameter and a version parameter. For example, to fetch the five most recent posts:
GET /ghost/api/content/posts?limit=5&key=YOUR_PUBLIC_API_KEY&version=v5.0
The response includes an posts array with each post containing id, title, slug, published_at, and html fields. You can also request related data using the include parameter:
GET /ghost/api/content/posts?include=authors,tags&key=YOUR_PUBLIC_API_KEY&version=v5.0
Working Example: Fetching Posts with Author Data
Here's a complete example using JavaScript's fetch to retrieve posts with their authors:
const API_KEY = 'YOUR_PUBLIC_API_KEY';
const API_URL = 'https://your-ghost-blog.com/ghost/api/content/posts';
async function getPosts() {
const url = new URL(API_URL);
url.searchParams.set('key', API_KEY);
url.searchParams.set('version', 'v5.0');
url.searchParams.set('limit', 10);
url.searchParams.set('include', 'authors,tags');
url.searchParams.set('formats', 'html,plaintext');
const response = await fetch(url);
const data = await response.json();
return data.posts.map(post => ({
title: post.title,
slug: post.slug,
publishedAt: post.published_at,
author: post.authors[0]?.name,
excerpt: post.plaintext?.substring(0, 200) || '',
html: post.html
}));
}
getPosts().then(console.log);
This returns an array of post objects ready for rendering in your application.
Filtering and Pagination
The Content API supports filtering via the where parameter and pagination through limit and page. For example, to get posts published in 2024:
GET /ghost/api/content/posts?filter=published_at:>=2024-01-01,published_at:<=2024-12-31&key=YOUR_PUBLIC_API_KEY&version=v5.0
Pagination headers like X-Total-Count and X-Total-Pages let you build efficient navigation:
const response = await fetch(url);
const totalPosts = parseInt(response.headers.get('X-Total-Count'));
const totalPages = parseInt(response.headers.get('X-Total-Pages'));
Trade-offs and Limitations
While the Content API is ideal for read operations, it has important constraints:
- Rate limiting varies by hosting provider and may block aggressive requests
- No write access—creating or editing posts requires the Admin API with proper authentication
- Version dependency—API responses can differ between v3, v4, and v5; always specify your version
- Public exposure—never embed your Admin API key in client-side code
Verifying Your Setup
Test your integration by:
- Starting a local Ghost instance via
ghost-cli - Generating a public integration key in Admin
- Running a simple curl request:
curl "http://localhost:2368/ghost/api/content/posts?key=YOUR_KEY&version=v5.0" - Checking that the JSON response contains posts with expected fields
If you're using a managed Ghost(Pro) host, contact support if you encounter unexpected rate limits.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.