---
name: Neynar
description: Use when building Farcaster applications, bots, mini apps, or integrations. Reach for this skill when you need to query Farcaster data (users, casts, feeds), write data to Farcaster (publish casts, manage signers), build interactive frames or mini apps, set up webhooks for real-time events, or manage user authentication and onboarding on Farcaster.
metadata:
    mintlify-proj: neynar
    version: "1.0"
---

# Neynar Skill Reference

## Product Summary

Neynar is an API platform that abstracts away the complexity of building on Farcaster, a decentralized social protocol. It provides REST APIs, a Node.js SDK, and tools for querying user data, social graphs, and content (casts), plus writing capabilities for publishing casts, managing signers, and building interactive experiences. The primary SDK is `@neynar/nodejs-sdk` (v2+), installed via npm. Key files: `.env` for API keys, configuration files for signers and webhooks. Primary docs: https://docs.neynar.com

## When to Use

Reach for Neynar when:
- **Querying Farcaster data**: Fetch user profiles, casts, feeds, followers, reactions, channels
- **Writing to Farcaster**: Publish casts, like/recast, update user profiles, manage signers
- **Building bots or agents**: Create automated Farcaster accounts with signers that can post and interact
- **Building mini apps or frames**: Create interactive experiences embedded in Farcaster clients
- **User authentication**: Implement Sign In with Neynar (SIWN) or managed signers for user onboarding
- **Real-time events**: Set up webhooks to listen for cast creation, user updates, mentions
- **Onchain integration**: Fetch user balances, deploy tokens, mint NFTs, intersect onchain and social data

Do not use Neynar for: Direct Farcaster Hub queries (use Snapchain gRPC API instead), local-only operations, or non-Farcaster social platforms.

## Quick Reference

### Installation & Setup

```bash
npm install @neynar/nodejs-sdk
```

Initialize client:
```typescript
import { NeynarAPIClient, Configuration } from "@neynar/nodejs-sdk";

const config = new Configuration({
  apiKey: process.env.NEYNAR_API_KEY,
});
const client = new NeynarAPIClient(config);
```

### Core Concepts

| Concept | Definition |
|---------|-----------|
| **FID** | Farcaster ID — permanent numerical identifier for each user |
| **Cast** | Unit of content (like a tweet); has unique hash |
| **Signer** | Cryptographic key that signs messages on behalf of a user or bot |
| **Feed** | Collection of casts, often based on social graph or channel |
| **Webhook** | Real-time event subscription (cast.created, user.updated, mentions) |

### Common API Endpoints (Node.js SDK)

| Task | SDK Method |
|------|-----------|
| Fetch user by FID | `client.fetchBulkUsers({ fids })` |
| Fetch user by username | `client.lookupUserByUsername({ username })` |
| Fetch user feed | `client.fetchFeed({ feedType, fid })` |
| Publish cast | `client.publishCast({ signerUuid, text })` |
| Like/recast | `client.publishReaction({ signerUuid, reactionType, target })` |
| Search casts | `client.searchCasts({ q, limit })` |
| Fetch cast info | `client.lookupCastByHashOrUrl({ hashOrUrl })` |
| Create signer | `client.createSigner()` |
| Lookup signer status | `client.lookupSigner({ signerUuid })` |
| Publish webhook | `client.publishWebhook({ targetUrl, events })` |

### Rate Limits (per subscription plan)

| Plan | Global RPM | Per-Endpoint RPM | RPS |
|------|-----------|-----------------|-----|
| Starter | 500 | 300 | 5 |
| Growth | 1000 | 600 | 10 |
| Scale | 2000 | 1200 | 20 |

Special limits: `/validate`, `/signer`, `signer/developer_managed` don't count toward global limits. Cast search: 60–240 RPM depending on plan.

### Environment Variables

```bash
NEYNAR_API_KEY=your_api_key_here
NEYNAR_SIGNER=signer_uuid_for_bot_or_app
```

## Decision Guidance

### When to Use Each Signer Type

| Signer Type | Use When | Tradeoffs |
|-------------|----------|-----------|
| **SIWN (Sign In with Neynar)** | Building mini apps, want plug-and-play auth, users don't pay gas | Limited UI customization; Neynar-branded approval screen |
| **Managed Signers** | Need custom branding on approval screen, building with other auth providers (Privy), want full API access | Must build your own auth flow; users may create new signer each login |
| **Developer-Managed Signers** | Need full custody of signers, maximum control | Most complex; you handle secure storage, message signing, auth flow; users pay for signer creation |

**Recommendation**: Use SIWN for most cases. Use Managed Signers if you need custom branding. Avoid Developer-Managed unless you have specific custody requirements.

### When to Use Each Data Fetch Method

| Method | Use When |
|--------|----------|
| `fetchBulkUsers` | Fetching multiple users by FID (batch operation) |
| `lookupUserByUsername` | Single user lookup by username |
| `fetchBulkUsersByEthOrSolAddress` | Finding users by wallet address |
| `fetchFeed` | Getting a user's personalized feed (following, trending, etc.) |
| `searchCasts` | Full-text search across casts (limited to 60–240 RPM) |

## Workflow

### 1. Fetch User Data

```typescript
// Get user by FID
const users = await client.fetchBulkUsers({ fids: [3, 5] });
console.log(users.users[0].username);

// Get user by username
const user = await client.lookupUserByUsername({ username: "dwr.eth" });
console.log(user.user.fid);
```

### 2. Fetch and Display Feeds

```typescript
import { FeedType } from "@neynar/nodejs-sdk/build/api";

const feed = await client.fetchFeed({
  feedType: FeedType.Following,
  fid: 3,
  limit: 50,
});
console.log(feed.casts.length);
```

### 3. Publish a Cast (with Signer)

```typescript
const cast = await client.publishCast({
  signerUuid: process.env.NEYNAR_SIGNER,
  text: "Hello Farcaster!",
});
console.log(cast.hash);
```

### 4. Set Up Webhooks for Real-Time Events

```typescript
// Create webhook via SDK
const webhook = await client.publishWebhook({
  targetUrl: "https://your-api.com/webhooks/neynar",
  events: [
    {
      event: "cast.created",
      subscriptions: [
        {
          subscriptionType: "Authors",
          authors: [3], // Watch user FID 3
        },
      ],
    },
  ],
});

// Handle incoming webhook on your backend
app.post("/webhooks/neynar", (req, res) => {
  const event = req.body;
  if (event.data.type === "cast.created") {
    console.log("New cast:", event.data.cast.text);
  }
  res.status(200).send("OK");
});
```

### 5. Create a Mini App

```bash
npx @neynar/create-farcaster-mini-app@latest
# Generates manifest, sets up local tunnel, includes demo API key
```

### 6. Validate Frame Actions

```typescript
const result = await client.validateFrameAction({
  messageBytesInHex: payload.trustedData.messageBytes,
});
console.log(result.valid, result.action.interactor.fid);
```

## Common Gotchas

- **Missing API key**: Always set `NEYNAR_API_KEY` in `.env`. Requests without it will fail with x402 error (pay-per-request).
- **Rate limit confusion**: Global and per-endpoint limits are separate. You can hit per-endpoint limit before global limit. `/validate` and `/signer` endpoints don't count toward global limits.
- **Signer status polling**: After creating a signer, poll `lookupSigner()` every 2–3 seconds until status is "approved". Don't assume immediate approval.
- **Cast creation limits**: If a user creates >1000 casts in 24h, they need 20% of that volume in available storage. Check storage before publishing high-volume casts.
- **Webhook timeouts**: Frame action POST requests to your webhook have a 5-second timeout. Keep handlers fast.
- **Frontend-only webhooks**: Webhooks require a backend. Cannot use on frontend-only apps.
- **FID vs username**: Always use FID for API calls when possible (faster, more reliable). Usernames can change; FIDs are permanent.
- **Embed validation**: When publishing casts with embeds (URLs, images), validate metadata first with `fetchEmbeddedUrlMetadata()`.
- **Deprecated SDK v1**: If using old `@neynar/nodejs-sdk` v1, migrate to v2. v1 is no longer maintained.

## Verification Checklist

Before submitting work with Neynar:

- [ ] API key is set in `.env` and not committed to version control
- [ ] SDK is installed (`npm install @neynar/nodejs-sdk`) and version is v2+
- [ ] Client is initialized with `Configuration` and `NeynarAPIClient`
- [ ] All API calls are wrapped in try-catch blocks for error handling
- [ ] Rate limits are respected (check plan limits, don't exceed RPM/RPS)
- [ ] Signer UUID is valid and status is "approved" before publishing
- [ ] Webhook target URL is publicly accessible and returns 200 OK
- [ ] FIDs are used instead of usernames where possible
- [ ] Cast text is under 320 characters (Farcaster limit)
- [ ] Frame action validation uses `validateFrameAction()` before processing
- [ ] Sensitive data (API keys, signer UUIDs) is never logged or exposed in client-side code

## Resources

- **Comprehensive page listing**: https://docs.neynar.com/llms.txt
- **API Reference**: https://docs.neynar.com/reference/quickstart
- **Node.js SDK Docs**: https://docs.neynar.com/nodejs-sdk/overview
- **Getting Started Guide**: https://docs.neynar.com/docs/getting-started-with-neynar

---

> For additional documentation and navigation, see: https://docs.neynar.com/llms.txt