> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scraperize.com/llms.txt
> Use this file to discover all available pages before exploring further.

# User posts

> An account's posts, newest first, as on its profile's Posts tab: its posts, reposts and its own threads, with the pinned post first on page 1. About 30 per page, with a `cursor` for the next page. Each post has its text, hashtags, mentions and links, the author, like / repost / reply / quote / bookmark counts, images, video or link preview, the quoted post (or embedded feed, list or starter pack), reply context (parent, root and grandparent author), who reposted it and when, reply restrictions and content labels.

Pass exactly one of `handle` or `userId`.

<Info>
  **Cost: 1 credit** per successful request. Errors and cache hits (`cache_max_age`) are free.
</Info>

<Accordion title="Copy for AI assistant" icon="sparkles">
  Paste this into ChatGPT, Claude or your coding assistant to generate working code for this endpoint (use the copy button).

  ```text Prompt
  I want to make an API call to /v1/bluesky/user/posts. Here are the details:

  Endpoint: GET https://api.scraperize.com/v1/bluesky/user/posts
  Description: An account's posts, newest first, as on its profile's Posts tab: its posts, reposts and its own threads, with the pinned post first on page 1. About 30 per page, with a `cursor` for the next page. Each post has its text, hashtags, mentions and links, the author, like / repost / reply / quote / bookmark counts, images, video or link preview, the quoted post (or embedded feed, list or starter pack), reply context (parent, root and grandparent author), who reposted it and when, reply restrictions and content labels.

  Required Headers:
  - x-api-key: Your API key

  Parameters:
  - handle (string): Bluesky handle, e.g. `espn.com` or `name.bsky.social` (a leading `@` or a `bsky.app/profile/...` URL also work). Required unless `userId` is given.
  - userId (string): The account DID, e.g. `did:plc:x7d6j54pm22ufehkes6jo4jf`. Required unless `handle` is given.
  - cursor (string): The `cursor` from the previous page, to get the next one.
  - cache_max_age (select): Optional. Return a cached result if one this age or newer exists — served for **0 credits** with `meta.cached=true` and `meta.cachedAt`. Otherwise a fresh scrape runs (**1 credit**) and refreshes the cache. Omit to always scrape fresh.

  Example Response:
  {
    "data": {
      "user": {
        "did": "did:plc:x7d6j54pm22ufehkes6jo4jf",
        "handle": "espn.com",
        "displayName": "ESPN",
        "url": "https://bsky.app/profile/espn.com",
        "avatarUrl": "https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie",
        "pronouns": null,
        "isVerified": true,
        "labels": [],
        "createdAt": "2024-11-25T21:49:49.345Z"
      },
      "posts": [
        {
          "id": "3muznlkmspz2x",
          "uri": "at://did:plc:x7d6j54pm22ufehkes6jo4jf/app.bsky.feed.post/3muznlkmspz2x",
          "cid": "bafyreiceaay7jrgqznvxhttsmizofewx3mj6bwebjtz76nd2wh4hix4fty",
          "url": "https://bsky.app/profile/espn.com/post/3muznlkmspz2x",
          "text": "One more sleep until NFL football is BACK. 🏈",
          "createdAt": "2026-09-08T18:27:24.700Z",
          "indexedAt": "2026-09-08T18:27:30.159Z",
          "langs": [],
          "tags": [],
          "via": null,
          "hashtags": [],
          "mentions": [],
          "links": [],
          "author": {
            "did": "did:plc:x7d6j54pm22ufehkes6jo4jf",
            "handle": "espn.com",
            "displayName": "ESPN",
            "url": "https://bsky.app/profile/espn.com",
            "avatarUrl": "https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie",
            "pronouns": null,
            "isVerified": true,
            "labels": [],
            "createdAt": "2024-11-25T21:49:49.345Z"
          },
          "likeCount": 100,
          "repostCount": 11,
          "replyCount": 11,
          "quoteCount": 6,
          "bookmarkCount": 0,
          "media": {
            "images": [],
            "video": {
              "playlistUrl": "https://video.bsky.app/watch/did%3Aplc%3Ax7d6j54pm22ufehkes6jo4jf/bafkreiflqivgi6afl5jv4qnmwzo3ks7jwe2dfurohsjfgafbtd5crw4gaq/playlist.m3u8",
              "thumbnailUrl": "https://video.bsky.app/watch/did%3Aplc%3Ax7d6j54pm22ufehkes6jo4jf/bafkreiflqivgi6afl5jv4qnmwzo3ks7jwe2dfurohsjfgafbtd5crw4gaq/thumbnail.jpg",
              "alt": null,
              "width": null,
              "height": null
            },
            "link": null
          },
          "quote": null,
          "embeddedRecord": null,
          "isReply": false,
          "reply": null,
          "isRepost": false,
          "repostedBy": null,
          "repostedAt": null,
          "isPinned": false,
          "threadPostIndex": null,
          "threadPostCount": null,
          "replySettings": null,
          "labels": []
        }
      ],
      "count": 30,
      "cursor": "2025-09-25T17:06:11.912Z",
      "hasMore": true,
      "fetchedAt": "2026-10-17T19:15:44.136Z"
    },
    "meta": {
      "requestId": "req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f",
      "creditsCharged": 1,
      "creditsRemaining": 4999,
      "cached": false
    }
  }

  Please help me write code in my preferred programming language to make this API call and handle the response appropriately. Include error handling and best practices.
  ```
</Accordion>


## OpenAPI

````yaml /api-reference/openapi.json get /v1/bluesky/user/posts
openapi: 3.0.3
info:
  title: Scraperize API
  version: 1.0.0
  description: >-
    Extract public data from social media platforms as clean JSON. Endpoints are
    split by platform and by what they return, e.g. `GET /v1/twitter/tweet`.


    ## Authentication

    Send your API key in the `x-api-key` header (or `Authorization: Bearer
    <key>`). Create keys in your dashboard.


    ## Credits

    Each successful live scrape costs **1 credit**. Credits are prepaid and
    never expire.


    ## Caching

    Every endpoint accepts an optional `cache_max_age`
    (`1d`|`3d`|`7d`|`14d`|`30d`). A cache hit within that window is returned for
    **0 credits**.


    ## Responses

    Success returns `{ "data": …, "meta": { "requestId", … } }`. Errors return
    `{ "error": { "code", "message", "requestId" } }` with a matching HTTP
    status. `meta` on a scrape carries `creditsCharged`, `creditsRemaining`,
    `cached`, and (on a hit) `cachedAt`.


    ## Rate limits

    Requests are limited per team per minute; over the limit returns `429` with
    a `Retry-After` header.
servers:
  - url: https://api.scraperize.com
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: Twitter
    description: Twitter / X scraping endpoints
  - name: Facebook
    description: Facebook scraping endpoints
  - name: Linkme
    description: Linkme (link.me) scraping endpoints
  - name: Amazon
    description: Amazon (creator shop / storefront) scraping endpoints
  - name: Linkbio
    description: Linkbio (lnk.bio) scraping endpoints
  - name: Pillar
    description: Pillar (pillar.io) scraping endpoints
  - name: Komi
    description: Komi (komi.io) scraping endpoints
  - name: Linktree
    description: Linktree (linktr.ee) scraping endpoints
  - name: Kick
    description: Kick (kick.com) scraping endpoints
  - name: Snapchat
    description: Snapchat (snapchat.com) scraping endpoints
  - name: Telegram
    description: Telegram (t.me) scraping endpoints
  - name: LinkedIn
    description: LinkedIn scraping endpoints
  - name: Twitch
    description: Twitch scraping endpoints
  - name: TikTok
    description: TikTok (tiktok.com) scraping endpoints
  - name: Instagram
    description: Instagram scraping endpoints
  - name: Lagos Life
    description: Lagos Life scraping endpoints
  - name: Bluesky
    description: Bluesky (bsky.app) scraping endpoints
paths:
  /v1/bluesky/user/posts:
    get:
      tags:
        - Bluesky
      summary: User posts
      description: >-
        An account's posts, newest first, as on its profile's Posts tab: its
        posts, reposts and its own threads, with the pinned post first on page
        1. About 30 per page, with a `cursor` for the next page. Each post has
        its text, hashtags, mentions and links, the author, like / repost /
        reply / quote / bookmark counts, images, video or link preview, the
        quoted post (or embedded feed, list or starter pack), reply context
        (parent, root and grandparent author), who reposted it and when, reply
        restrictions and content labels.


        Pass exactly one of `handle` or `userId`.
      parameters:
        - name: handle
          in: query
          required: false
          description: >-
            Bluesky handle, e.g. `espn.com` or `name.bsky.social` (a leading `@`
            or a `bsky.app/profile/...` URL also work). Required unless `userId`
            is given.
          schema:
            type: string
          example: espn.com
        - name: userId
          in: query
          required: false
          description: >-
            The account DID, e.g. `did:plc:x7d6j54pm22ufehkes6jo4jf`. Required
            unless `handle` is given.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: The `cursor` from the previous page, to get the next one.
          schema:
            type: string
        - name: cache_max_age
          in: query
          required: false
          description: >-
            Optional. Return a cached result if one this age or newer exists —
            served for **0 credits** with `meta.cached=true` and
            `meta.cachedAt`. Otherwise a fresh scrape runs (**1 credit**) and
            refreshes the cache. Omit to always scrape fresh.
          schema:
            type: string
            enum:
              - 1d
              - 3d
              - 7d
              - 14d
              - 30d
          example: 7d
      responses:
        '200':
          description: A page of the account's posts.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      user:
                        type: object
                        nullable: true
                      posts:
                        type: array
                        items:
                          type: object
                      count:
                        type: integer
                      cursor:
                        type: string
                        nullable: true
                      hasMore:
                        type: boolean
                      fetchedAt:
                        type: string
                        format: date-time
                  meta:
                    type: object
                    description: >-
                      requestId + credit/caching metadata (creditsCharged,
                      creditsRemaining, cached, cachedAt).
                required:
                  - data
                  - meta
              example:
                data:
                  user:
                    did: did:plc:x7d6j54pm22ufehkes6jo4jf
                    handle: espn.com
                    displayName: ESPN
                    url: https://bsky.app/profile/espn.com
                    avatarUrl: >-
                      https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie
                    pronouns: null
                    isVerified: true
                    labels: []
                    createdAt: '2024-11-25T21:49:49.345Z'
                  posts:
                    - id: 3muznlkmspz2x
                      uri: >-
                        at://did:plc:x7d6j54pm22ufehkes6jo4jf/app.bsky.feed.post/3muznlkmspz2x
                      cid: >-
                        bafyreiceaay7jrgqznvxhttsmizofewx3mj6bwebjtz76nd2wh4hix4fty
                      url: https://bsky.app/profile/espn.com/post/3muznlkmspz2x
                      text: One more sleep until NFL football is BACK. 🏈
                      createdAt: '2026-09-08T18:27:24.700Z'
                      indexedAt: '2026-09-08T18:27:30.159Z'
                      langs: []
                      tags: []
                      via: null
                      hashtags: []
                      mentions: []
                      links: []
                      author:
                        did: did:plc:x7d6j54pm22ufehkes6jo4jf
                        handle: espn.com
                        displayName: ESPN
                        url: https://bsky.app/profile/espn.com
                        avatarUrl: >-
                          https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie
                        pronouns: null
                        isVerified: true
                        labels: []
                        createdAt: '2024-11-25T21:49:49.345Z'
                      likeCount: 100
                      repostCount: 11
                      replyCount: 11
                      quoteCount: 6
                      bookmarkCount: 0
                      media:
                        images: []
                        video:
                          playlistUrl: >-
                            https://video.bsky.app/watch/did%3Aplc%3Ax7d6j54pm22ufehkes6jo4jf/bafkreiflqivgi6afl5jv4qnmwzo3ks7jwe2dfurohsjfgafbtd5crw4gaq/playlist.m3u8
                          thumbnailUrl: >-
                            https://video.bsky.app/watch/did%3Aplc%3Ax7d6j54pm22ufehkes6jo4jf/bafkreiflqivgi6afl5jv4qnmwzo3ks7jwe2dfurohsjfgafbtd5crw4gaq/thumbnail.jpg
                          alt: null
                          width: null
                          height: null
                        link: null
                      quote: null
                      embeddedRecord: null
                      isReply: false
                      reply: null
                      isRepost: false
                      repostedBy: null
                      repostedAt: null
                      isPinned: false
                      threadPostIndex: null
                      threadPostCount: null
                      replySettings: null
                      labels: []
                    - id: 3mpglmolczz2w
                      uri: >-
                        at://did:plc:x7d6j54pm22ufehkes6jo4jf/app.bsky.feed.post/3mpglmolczz2w
                      cid: >-
                        bafyreid2eoctnshw7unb5ozrjqsy63kpqmwwvhj2xuxsfo4z5zucfazqum
                      url: https://bsky.app/profile/espn.com/post/3mpglmolczz2w
                      text: >-
                        Former Tennessee Titans and Arizona Cardinals running
                        back Chris Johnson revealed that he has been diagnosed
                        with ALS in an interview with ABC's "Good Morning
                        America".


                        Johnson, 39, told GMA co-anchor Michael Strahan that he
                        was diagnosed with the disease in 2025.
                      createdAt: '2026-06-29T13:25:44.562Z'
                      indexedAt: '2026-06-29T13:25:45.268Z'
                      langs: []
                      tags: []
                      via: null
                      hashtags: []
                      mentions: []
                      links: []
                      author:
                        did: did:plc:x7d6j54pm22ufehkes6jo4jf
                        handle: espn.com
                        displayName: ESPN
                        url: https://bsky.app/profile/espn.com
                        avatarUrl: >-
                          https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie
                        pronouns: null
                        isVerified: true
                        labels: []
                        createdAt: '2024-11-25T21:49:49.345Z'
                      likeCount: 137
                      repostCount: 34
                      replyCount: 16
                      quoteCount: 17
                      bookmarkCount: 1
                      media:
                        images: []
                        video: null
                        link:
                          url: http://spr.ly/63329BDvG6W
                          title: Former NFL RB Chris Johnson discusses ALS diagnosis
                          description: >-
                            Former Titans and Cardinals running back Chris
                            Johnson told "Good Morning America" that he was
                            diagnosed with ALS in 2025.
                          thumbnailUrl: >-
                            https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreicgzhnme4wgvolagtic3dki5icwfkmlxz23cmakg2mj2h4xkwvg2q
                      quote: null
                      embeddedRecord: null
                      isReply: false
                      reply: null
                      isRepost: false
                      repostedBy: null
                      repostedAt: null
                      isPinned: false
                      threadPostIndex: null
                      threadPostCount: null
                      replySettings: null
                      labels: []
                    - id: 3mov4cob7hn2x
                      uri: >-
                        at://did:plc:x7d6j54pm22ufehkes6jo4jf/app.bsky.feed.post/3mov4cob7hn2x
                      cid: >-
                        bafyreihvnizv4s2h72qtu2cbglugxldzs32rbctwfcj73mrc4mevvn5ux4
                      url: https://bsky.app/profile/espn.com/post/3mov4cob7hn2x
                      text: >-
                        Breaking: Michigan coach Dusty May is finalizing a deal
                        to take the Dallas Mavericks head coaching job, sources
                        tell Pete Thamel, Shams Charania and Adam Schefter.
                      createdAt: '2026-06-22T14:36:26.839Z'
                      indexedAt: '2026-06-22T14:36:28.062Z'
                      langs: []
                      tags: []
                      via: null
                      hashtags: []
                      mentions: []
                      links: []
                      author:
                        did: did:plc:x7d6j54pm22ufehkes6jo4jf
                        handle: espn.com
                        displayName: ESPN
                        url: https://bsky.app/profile/espn.com
                        avatarUrl: >-
                          https://cdn.bsky.app/img/avatar/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreie4oxawqqsfzvk47ysr3unsnmviedzpylxmwxnpa534to2bzas4ie
                        pronouns: null
                        isVerified: true
                        labels: []
                        createdAt: '2024-11-25T21:49:49.345Z'
                      likeCount: 145
                      repostCount: 25
                      replyCount: 15
                      quoteCount: 57
                      bookmarkCount: 2
                      media:
                        images:
                          - url: >-
                              https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreihdlyxrpv3lvnxk6vi6x5tbewwj7o3ix7wkcxgfgetqukqxfbefta
                            thumbnailUrl: >-
                              https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:x7d6j54pm22ufehkes6jo4jf/bafkreihdlyxrpv3lvnxk6vi6x5tbewwj7o3ix7wkcxgfgetqukqxfbefta
                            alt: >-
                              Michigan men's basketball coach Dusty May is
                              finalizing a deal to take the Dallas Mavericks
                              head coaching job, sources tell Pete Thamel, Shams
                              Charania and Adam Schefter.
                            width: 720
                            height: 900
                        video: null
                        link: null
                      quote: null
                      embeddedRecord: null
                      isReply: false
                      reply: null
                      isRepost: false
                      repostedBy: null
                      repostedAt: null
                      isPinned: false
                      threadPostIndex: null
                      threadPostCount: null
                      replySettings: null
                      labels: []
                  count: 30
                  cursor: '2025-09-25T17:06:11.912Z'
                  hasMore: true
                  fetchedAt: '2026-10-17T19:15:44.136Z'
                meta:
                  requestId: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
                  creditsCharged: 1
                  creditsRemaining: 4999
                  cached: false
        '400':
          description: Invalid or expired cursor.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: BAD_REQUEST
                  message: The request was invalid.
                  requestId: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
        '401':
          description: Missing, invalid, or revoked API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: UNAUTHORIZED
                  message: API key required — pass it in the `x-api-key` header.
                  requestId: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
        '402':
          description: Not enough credits for this request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INSUFFICIENT_CREDITS
                  message: >-
                    This request costs 1 credit, but your balance is 0. Top up
                    to continue.
                  requestId: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
        '404':
          description: >-
            Account not found, deactivated, suspended, or hidden from logged-out
            viewers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: NOT_FOUND
                  message: >-
                    The requested content was not found (it may not exist, be
                    deleted, or be private).
                  requestId: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
        '422':
          description: >-
            Invalid query parameters (neither or both of handle / userId, or a
            malformed value).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: VALIDATION_ERROR
                  message: Request validation failed
                  requestId: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
                  details:
                    - path: url
                      message: url is required
        '429':
          description: Over the per-minute rate limit — honour `Retry-After`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: RATE_LIMITED
                  message: >-
                    Rate limit exceeded — max 100 requests per 60s. Retry in
                    ~30s.
                  requestId: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
        '503':
          description: >-
            Temporarily unavailable — retry after `Retry-After`. `error.code`
            tells you why: `UPSTREAM_BLOCKED` (the source blocked this request),
            `EXTRACTION_FAILED` (the source returned unexpected data),
            `PLATFORM_UNAVAILABLE` (the source is down), or
            `SERVICE_UNAVAILABLE` (we are at capacity).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: UPSTREAM_BLOCKED
                  message: >-
                    The source is temporarily unavailable. Please try again
                    shortly.
                  requestId: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: NOT_FOUND
            message:
              type: string
              example: The requested content was not found.
            requestId:
              type: string
              example: req_8f0c2b7e-1a2b-4c3d-9e8f-0a1b2c3d4e5f
            details:
              type: array
              items:
                type: object
              description: Present on validation errors.
          required:
            - code
            - message
            - requestId
      required:
        - error
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Your API key. Send it in the `x-api-key` header (or `Authorization:
        Bearer <key>`). Create and manage keys from your dashboard.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.