# RealWorld API Pagination Parameters: Offset, Limit, and Implementation Guide

> Discover RealWorld API pagination using limit and offset parameters. Learn implementation details and conventions for efficient data retrieval.

- Repository: [Thinkster/realworld](https://github.com/gothinkster/realworld)
- Tags: api-reference
- Published: 2026-02-28

---

**The RealWorld API utilizes offset-based pagination controlled by `limit` and `offset` query parameters, returning a default of 10 items per page in the actual implementation while the OpenAPI specification defines a default limit of 20.**

The gothinkster/realworld repository provides a comprehensive Medium-clone specification used to demonstrate full-stack implementations across various frameworks. Understanding the RealWorld API pagination parameters is essential for correctly consuming collection endpoints such as articles, feeds, and tags, as the implementation follows strict conventions defined in the OpenAPI contract but contains specific default behaviors in the route handlers.

## OpenAPI Specification vs. Implementation Defaults

The canonical API contract resides in [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml), which defines reusable parameter components for pagination:

- **`offset`** (`offsetParam`): An optional integer starting at 0 that specifies how many items to skip before returning results.
- **`limit`** (`limitParam`): An optional integer with a minimum value of 1 that caps the number of items returned.

According to the OpenAPI description, the `limit` parameter advertises a **default value of 20 items** when omitted. However, the actual implementation diverges slightly from this specification.

## Route Handler Implementation

In the production route handlers, query parameters are parsed directly from the request and fallback to different defaults than those documented in the spec.

In [`apps/api/server/routes/api/articles/index.get.ts`](https://github.com/gothinkster/realworld/blob/main/apps/api/server/routes/api/articles/index.get.ts), the handler executes:

```typescript
skip: Number(query.offset) || 0,
take: Number(query.limit) || 10,

```

Similarly, the authenticated feed endpoint in [`apps/api/server/routes/api/articles/feed.get.ts`](https://github.com/gothinkster/realworld/blob/main/apps/api/server/routes/api/articles/feed.get.ts) implements identical logic:

```typescript
skip: Number(query.offset) || 0,
take: Number(query.limit) || 10,

```

This means the **effective default limit is 10 items**, not 20, when clients omit the `limit` parameter. Both handlers map the `offset` query parameter to a `skip` value and `limit` to `take` for the underlying data layer.

## Pagination Conventions and Response Structure

The RealWorld API follows strict conventions to ensure predictable client behavior across all collection endpoints:

- **Zero-based offset**: The first item starts at `offset=0`, making page calculation straightforward.
- **Query string only**: Parameters are passed exclusively as URL query parameters (e.g., `?limit=5&offset=10`), never as body parameters or headers.
- **Consistent response envelope**: Every paginated endpoint returns an object containing both the data array and a total count. For articles, this is `articles` and `articlesCount`, matching the `MultipleArticlesResponse` schema defined in [`openapi.yml`](https://github.com/gothinkster/realworld/blob/main/openapi.yml).
- **Client-side page calculation**: Because the response includes `articlesCount`, clients can compute total pages using `Math.ceil(articlesCount / limit)`.

## Practical Usage Examples

### Fetch the First Page with Default Limit

```javascript
fetch('https://api.realworld.show/api/articles')
  .then(r => r.json())
  .then(data => {
    console.log('Articles returned:', data.articles.length);
    console.log('Total count:', data.articlesCount);
  });

```

### Request a Specific Page Using cURL

```bash
curl -G "https://api.realworld.show/api/articles" \
  --data-urlencode "limit=5" \
  --data-urlencode "offset=10"

```

### Paginate the Authenticated Feed

```javascript
const token = 'YOUR_JWT_TOKEN';
fetch('https://api.realworld.show/api/articles/feed?limit=3&offset=6', {
  headers: { Authorization: `Token ${token}` },
})
  .then(r => r.json())
  .then(data => console.log(data));

```

### Calculate Total Pages on the Client

```javascript
function totalPages(count, limit = 10) {
  return Math.ceil(count / limit);
}

fetch('https://api.realworld.show/api/articles')
  .then(r => r.json())
  .then(({ articlesCount }) => {
    console.log('Total pages:', totalPages(articlesCount));
  });

```

## Testing and Validation

The repository includes end-to-end validation in `specs/api/hurl/pagination.hurl`, which registers a test user, creates multiple articles, and verifies that the pagination logic correctly respects `limit` and `offset` values. This test confirms that setting `limit=1` and `offset=1` returns exactly one item starting from the second record in the collection.

## Summary

- The RealWorld API implements **offset-based pagination** using `offset` and `limit` query parameters defined in [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml).
- The OpenAPI spec lists a default limit of **20**, but the implementation in [`apps/api/server/routes/api/articles/index.get.ts`](https://github.com/gothinkster/realworld/blob/main/apps/api/server/routes/api/articles/index.get.ts) and [`feed.get.ts`](https://github.com/gothinkster/realworld/blob/main/feed.get.ts) defaults to **10 items**.
- Pagination uses **zero-based indexing**, where `offset=0` returns the first page.
- Responses include a total count field (e.g., `articlesCount`) alongside the data array, enabling client-side calculation of total pages.
- All pagination parameters are transmitted via query strings, not request bodies.

## Frequently Asked Questions

### What are the default pagination values in the RealWorld API?

The implementation defaults to `offset=0` and `limit=10` when query parameters are omitted, though the OpenAPI specification in [`specs/api/openapi.yml`](https://github.com/gothinkster/realworld/blob/main/specs/api/openapi.yml) documents a default limit of 20. Developers should assume a default of 10 items per page when integrating with the actual API implementation.

### How does the RealWorld API return total record counts for pagination?

Every paginated endpoint returns a response object containing both the data array (e.g., `articles`) and a total count field (e.g., `articlesCount`). This allows clients to calculate the total number of available pages by dividing the total count by the requested limit and applying `Math.ceil()`.

### Can I request more than the default limit per page?

Yes, the API does not enforce a maximum limit in the route handlers, though the OpenAPI specification defines a minimum value of 1. Clients can request any page size by explicitly setting the `limit` parameter, but extremely large values may impact performance depending on the specific backend implementation.

### Does the feed endpoint use the same pagination as the global articles list?

Yes, the authenticated feed endpoint at `GET /api/articles/feed` uses identical pagination logic to the global articles endpoint. Both handlers reside in `apps/api/server/routes/api/articles/` and implement the same `skip`/`take` pattern with `offset` and `limit` query parameters.