# How to list Yahoo email messages

Source: https://developer.nylas.com/docs/cookbook/email/messages/list-messages-yahoo/

Yahoo Mail doesn't have a public REST API. There's no equivalent to Gmail's API or Microsoft Graph. Internally, Nylas connects to Yahoo accounts over IMAP, but you don't need to deal with IMAP protocols, socket connections, or MIME parsing yourself. The same [Messages API](/docs/reference/api/messages/) you use for Gmail and Outlook works for Yahoo.

This guide covers listing messages from Yahoo accounts, including the OAuth setup process, the 90-day message cache, and how to reach older messages when you need them.

## Is there a Yahoo Mail API?

Yahoo doesn't publish a public REST API for Mail. The only programmatic access is IMAP for reading and SMTP for sending, authenticated through Yahoo's OAuth 2.0 host at `api.login.yahoo.com`. There's no equivalent to the Gmail API or Microsoft Graph, so an integration either speaks IMAP directly or goes through a service that wraps it.

That host, `api.login.yahoo.com`, is where the OAuth authorization and token requests go once Yahoo issues you credentials, which requires signing a Commercial Access Agreement first. Reading mail still happens over IMAP, which exposes the last 90 days through the [message cache](#the-90-day-message-cache). This guide uses a unified REST layer so you read Yahoo mail with the same call you'd use for Gmail or Outlook.

## How do I list Yahoo Mail messages with the Nylas API?

Send a `GET` request to `/v3/grants/{grant_id}/messages` with your API key. Nylas connects to Yahoo over IMAP and returns the 50 most recent messages by default, up to 200 per page, in the same JSON schema used for Gmail and Outlook. Authenticate with OAuth or an app password. See [List messages](#list-messages) for the request and response.

## Why use Nylas instead of IMAP directly?

Yahoo's only developer-facing email interface is raw IMAP. That means building your own connection pooling, MIME parsing, and sync infrastructure from scratch. On top of the protocol complexity, Yahoo OAuth requires signing a Commercial Access Agreement before you can even get API credentials, and the IMAP search implementation has known gaps (no `NOT` operator support, for example).

Nylas wraps all of that in a REST API with JSON responses. You don't need to sign Yahoo's agreement yourself, manage IMAP sockets, or work around IMAP search limitations. Your code works across Yahoo, Gmail, Outlook, and every other provider without modification.

If you're only targeting Yahoo and are comfortable with IMAP, you can connect directly. For everything else, Nylas saves you significant development time.

## Before you begin

You'll need:

- A [Nylas application](/docs/v3/getting-started/) with a valid API key
- A [grant](/docs/v3/auth/) for a Yahoo Mail account
- A Yahoo OAuth connector configured with your Yahoo app credentials (see [Yahoo authentication guide](/docs/provider-guides/yahoo-authentication/))


> **Info:** 
> **New to Nylas?** Start with the [quickstart guide](/docs/v3/getting-started/) to set up your app and connect a test account before continuing here.


### Yahoo OAuth setup

Yahoo requires a few extra steps compared to Google or Microsoft. You'll need to:

1. **Request API access** by submitting the [Yahoo Mail API Access form](https://www.yahoo.com/). Yahoo will send you a Commercial Access Agreement to sign.
2. **Create a Yahoo app** by registering your application in the [Yahoo Apps dashboard](https://developer.yahoo.com/apps/) to get a client ID and secret.
3. **Create a Yahoo connector in Nylas** and configure it with your Yahoo client ID and secret.

Yahoo OAuth scopes are simpler than Google's tier system:

| Access level | Scopes required             |
| ------------ | --------------------------- |
| Read-only    | `email`, `mail-r`           |
| Read-write   | `email`, `mail-r`, `mail-w` |

You can only select one access level. Yahoo doesn't let you request both `mail-r` and `mail-w` separately.

If you'd rather skip the OAuth setup for testing, you can also authenticate Yahoo accounts using [IMAP with an app password](/docs/provider-guides/yahoo-authentication/#authenticate-yahoo-grants-with-app-password). This uses the `imap` provider type instead of `yahoo` and requires each user to generate an app password in their Yahoo account settings. OAuth is the better choice for production apps.

The full setup walkthrough is in the [Yahoo authentication guide](/docs/provider-guides/yahoo-authentication/).

## List messages

Make a [List Messages request](/docs/reference/api/messages/get-messages/) with the grant ID. By default, Nylas returns the 50 most recent messages. These examples limit results to 5:

```bash
curl --compressed --request GET \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?limit=5" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json'

```

```json
{
  "request_id": "d0c951b9-61db-4daa-ab19-cd44afeeabac",
  "data": [
    {
      "starred": false,
      "unread": true,
      "folders": ["UNREAD", "CATEGORY_PERSONAL", "INBOX"],
      "grant_id": "1",
      "date": 1706811644,
      "attachments": [
        {
          "id": "1",
          "grant_id": "1",
          "filename": "invite.ics",
          "size": 2504,
          "content_type": "text/calendar; charset=\"UTF-8\"; method=REQUEST"
        },
        {
          "id": "2",
          "grant_id": "1",
          "filename": "invite.ics",
          "size": 2504,
          "content_type": "application/ics; name=\"invite.ics\"",
          "is_inline": false,
          "content_disposition": "attachment; filename=\"invite.ics\""
        }
      ],
      "from": [
        {
          "name": "Nylas DevRel",
          "email": "nylasdev@nylas.com"
        }
      ],
      "id": "1",
      "object": "message",
      "snippet": "Send Email with Nylas APIs",
      "subject": "Learn how to Send Email with Nylas APIs",
      "thread_id": "1",
      "to": [
        {
          "name": "Nyla",
          "email": "nyla@nylas.com"
        }
      ],
      "created_at": 1706811644,
      "body": "Learn how to send emails using the Nylas APIs!"
    }
  ],
  "next_cursor": "123"
}


```

```js [listMessages-Node.js SDK]

import Nylas from "nylas";

const nylas = new Nylas({
  apiKey: "<NYLAS_API_KEY>",
  apiUri: "<NYLAS_API_URI>",
});

async function fetchRecentEmails() {
  try {
    const messages = await nylas.messages.list({
      identifier: "<NYLAS_GRANT_ID>",
      queryParams: {
        limit: 5,
      },
    });

    console.log("Messages:", messages);
  } catch (error) {
    console.error("Error fetching emails:", error);
  }
}

fetchRecentEmails();


```

```python [listMessages-Python SDK]

from nylas import Client

nylas = Client(
    "<NYLAS_API_KEY>",
    "<NYLAS_API_URI>"
)

grant_id = "<NYLAS_GRANT_ID>"

messages = nylas.messages.list(
  grant_id,
  query_params={
    "limit": 5
  }
)

print(messages)

```


```ruby [listMessages-Ruby SDK]
require 'nylas'

nylas = Nylas::Client.new(api_key: '<NYLAS_API_KEY>')
query_params = { limit: 5 }
messages, _ = nylas.messages.list(identifier: '<NYLAS_GRANT_ID>', query_params: query_params)

messages.each {|message|
  puts "[#{Time.at(message[:date]).strftime("%d/%m/%Y at %H:%M:%S")}] \
      #{message[:subject]}"
}
```

```java [listMessages-Java SDK]
import com.nylas.NylasClient;
import com.nylas.models.*;
import java.text.SimpleDateFormat;

public class ListMessages {
  public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError {
    NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
    ListMessagesQueryParams queryParams = new ListMessagesQueryParams.Builder().limit(5).build();
    ListResponse<Message> message = nylas.messages().list("<NYLAS_GRANT_ID>", queryParams);

    for(Message email : message.getData()) {
      String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").
          format(new java.util.Date((email.getDate() * 1000L)));

      System.out.println("[" + date + "] | " + email.getSubject());
    }
  }
}
```

```kt [listMessages-Kotlin SDK]
import com.nylas.NylasClient
import com.nylas.models.*
import java.text.SimpleDateFormat
import java.util.*

fun main(args: Array<String>) {
    val nylas = NylasClient(apiKey = "<NYLAS_API_KEY>")
    val queryParams = ListMessagesQueryParams(limit = 5)
    val messages = nylas.messages().list("<NYLAS_GRANT_ID>", queryParams).data

    for (message in messages) {
        val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
            .format(Date(message.date.toLong() * 1000))
        println("[$date] | ${message.subject}")
    }
}
```


## List Yahoo messages from the terminal

Yahoo Mail connects over IMAP, so you authenticate with OAuth or an app password and then read the mailbox the same way. The [Nylas CLI](https://cli.nylas.com/docs/commands) lists it from your terminal: `nylas email list` returns the 10 most recent inbox messages through the Messages API, with no code required.


The Nylas CLI mirrors the Messages API, so you can read the same inbox from your terminal without writing any code. After `nylas init` and `nylas auth login`, the `email list` command returns the 10 most recent inbox messages by default and pages through everything automatically once `--limit` goes over 200:

```bash
# List the 10 most recent inbox messages
nylas email list

# Show only unread messages from a specific sender
nylas email list --unread --from billing@vendor.com

# Fetch everything across all folders, paginated automatically
nylas email list --all --all-folders --max 500
```

To find specific messages rather than list them, `email search` runs a full-text query with its own filters for sender (`--from`), date range (`--after` and `--before`), and attachments (`--has-attachment`). Search returns 20 results by default and only fetches more than one page once `--limit` goes over 200:

```bash
# Full-text search restricted to one sender, attachments only
nylas email search "invoice" --from billing@vendor.com --has-attachment
```

Both commands accept `--json`, so you can pipe results into `jq` or a script. See the [`email list`](https://cli.nylas.com/docs/commands/email-list) and [`email search`](https://cli.nylas.com/docs/commands/email-search) command reference for every flag.


Yahoo exposes plain IMAP folder names, so `--folder` takes a readable value directly without an ID lookup. The one to remember is spam: Yahoo calls that folder `Bulk Mail`, not Junk or Spam. List the folders on an account, then read the flagged messages by name:

```bash
# See every folder name on the account, including custom ones
nylas email folders list

# Read the messages Yahoo flagged as spam
nylas email list --folder "Bulk Mail"
```

The cache keeps about 90 days of Yahoo mail searchable. To send Yahoo mail from the same command line, see [Send email from the terminal](https://cli.nylas.com/guides/send-email-from-terminal).

## Filter messages

You can narrow results with query parameters. Here's what works with Yahoo accounts:


| Parameter         | What it does                  | Example                       |
| ----------------- | ----------------------------- | ----------------------------- |
| `subject`         | Match on subject line         | `?subject=Weekly standup`     |
| `from`            | Filter by sender              | `?from=alex@example.com`      |
| `to`              | Filter by recipient           | `?to=team@company.com`        |
| `unread`          | Unread only                   | `?unread=true`                |
| `in`              | Filter by folder or label ID  | `?in=INBOX`                   |
| `received_after`  | After a Unix timestamp        | `?received_after=1706000000`  |
| `received_before` | Before a Unix timestamp       | `?received_before=1706100000` |
| `has_attachment`  | Only results with attachments | `?has_attachment=true`        |


Here's how to combine filters. This pulls unread messages from a specific sender:


```bash
curl --request GET \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?from=alex@example.com&unread=true&limit=10" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>'
```

```js [filterMessages-Node.js SDK]
const messages = await nylas.messages.list({
  identifier: grantId,
  queryParams: {
    from: "alex@example.com",
    unread: true,
    limit: 10,
  },
});
```

```python [filterMessages-Python SDK]
messages = nylas.messages.list(
    grant_id,
    query_params={
        "from": "alex@example.com",
        "unread": True,
        "limit": 10,
    }
)
```


### Search with `search_query_native`

Yahoo supports the `search_query_native` parameter for IMAP-style search. The `in`, `limit`, and `page_token` co-parameter restriction that Google and Microsoft enforce isn't documented for Yahoo, so you can pair `search_query_native` with standard filters like `from` and `subject`.

```bash
curl --request GET \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?search_query_native=subject:invoice&limit=10" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>'
```

```js [nativeSearchYahoo-Node.js SDK]
const messages = await nylas.messages.list({
  identifier: grantId,
  queryParams: {
    searchQueryNative: "subject:invoice",
    limit: 10,
  },
});
```

```python [nativeSearchYahoo-Python SDK]
messages = nylas.messages.list(
    grant_id,
    query_params={
        "search_query_native": "subject:invoice",
        "limit": 10,
    }
)
```

> **Warn:** 
> **Yahoo's IMAP search doesn't support `NOT` syntax.** If you use a negation query, the results may still contain messages you intended to exclude. Filter those out in your application code instead.

See the [search best practices guide](/docs/dev-guide/best-practices/search/) for more on `search_query_native` across providers.

## Things to know about Yahoo

Yahoo is IMAP-based, which means it behaves differently from Google and Microsoft in a few important ways.

### The 90-day message cache

This is the most important Yahoo-specific detail. Nylas maintains a rolling cache of messages from the last 90 days. Anything received or created within that window is synced and available through the API. Messages older than 90 days aren't in the cache, but you can still reach them by setting `query_imap=true` to query Yahoo's IMAP server directly. This is slower due to provider latency, but it gives you access to the full mailbox.


```bash
curl --request GET \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?query_imap=true&in=INBOX&limit=10" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>'
```

```js [queryImap-Node.js SDK]
const messages = await nylas.messages.list({
  identifier: grantId,
  queryParams: {
    queryImap: true,
    in: "INBOX",
    limit: 10,
  },
});
```

```python [queryImap-Python SDK]
messages = nylas.messages.list(
    grant_id,
    query_params={
        "query_imap": True,
        "in": "INBOX",
        "limit": 10,
    }
)
```

When using `query_imap`, you must include the `in` parameter to specify which folder to search.


### Webhooks don't cover old messages

Nylas [webhooks](/docs/v3/notifications/) only fire for changes to messages within the 90-day cache window. If a user modifies or deletes a message older than 90 days, you won't receive a notification. Plan your sync strategy accordingly if your app needs to track changes across the full mailbox.


### Yahoo uses standard IMAP folders

Unlike Microsoft's internal names (`sentitems`, `deleteditems`) or Google's label system, Yahoo uses straightforward IMAP folder names:

| Yahoo UI name    | Folder ID   |
| ---------------- | ----------- |
| Inbox            | `Inbox`     |
| Sent             | `Sent`      |
| Draft            | `Draft`     |
| Trash            | `Trash`     |
| Bulk Mail (Spam) | `Bulk Mail` |
| Archive          | `Archive`   |

Custom folders created by the user appear with their display names. Use the [List Folders endpoint](/docs/reference/api/folders/get-folder/) to get the complete list for a given account.

### Rate limits aren't publicized

Yahoo doesn't publish its API rate limits. If your app hits a rate limit, the response will include the duration you need to wait before retrying. Nylas handles retries automatically, but if you're making a high volume of requests for many Yahoo users, you may see throttling.

As with other providers, [webhooks](/docs/v3/notifications/) are the best way to avoid hitting rate limits. Let Nylas notify you of changes instead of polling.

### Sync and threading

Yahoo accounts in Nylas use IMAP for reading and SMTP for sending. This is invisible to your code, but it explains a few behaviors:

- **Sync is slower than Google or Microsoft** because those providers have native APIs with push notifications. Yahoo relies on periodic IMAP polling.
- **Message IDs** are IMAP UIDs, which are numeric values like `12345` that are unique within a folder but may not be globally unique across the account.
- **Thread grouping** relies on subject-line and header matching rather than a native threading system. This works well for most conversations but isn't as precise as Gmail's built-in `thread_id`.

### Two ways to authenticate

Yahoo supports two authentication methods in Nylas:

| Method                 | Provider type | Best for                                                                 |
| ---------------------- | ------------- | ------------------------------------------------------------------------ |
| Yahoo OAuth            | `yahoo`       | Production apps that want a smooth sign-in, no app passwords needed |
| IMAP with app password | `imap`        | Testing or apps where users already manage app passwords                 |

Yahoo OAuth is the recommended approach. It gives you a proper OAuth consent flow and doesn't require users to create app passwords. See the [Yahoo authentication guide](/docs/provider-guides/yahoo-authentication/) for both methods.

## Paginate through results


The Messages API returns paginated responses. When there are more results, the response includes a `next_cursor` value. Pass it back as `page_token` to get the next page:

```bash
curl --request GET \
  --url "https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/messages?limit=10&page_token=<NEXT_CURSOR>" \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>'
```

```js [paginateMessages-Node.js SDK]
let pageCursor = undefined;

do {
  const result = await nylas.messages.list({
    identifier: grantId,
    queryParams: {
      limit: 10,
      pageToken: pageCursor,
    },
  });

  // Process result.data here

  pageCursor = result.nextCursor;
} while (pageCursor);
```

```python [paginateMessages-Python SDK]
page_cursor = None

while True:
    query = {"limit": 10}
    if page_cursor:
        query["page_token"] = page_cursor

    result = nylas.messages.list(grant_id, query_params=query)

    # Process result.data here

    page_cursor = result.next_cursor
    if not page_cursor:
        break
```

Keep paginating until the response comes back without a `next_cursor`.


## What's next

- [List Yahoo Mail email threads](/docs/cookbook/email/threads/list-threads-yahoo/) to group these messages into conversations
- [List Gmail messages](/docs/cookbook/email/messages/list-messages-google/) for the same task on Google accounts
- [List Microsoft messages](/docs/cookbook/email/messages/list-messages-microsoft/) for the same task on Microsoft 365 accounts
- [Messages API reference](/docs/reference/api/messages/) for full endpoint documentation and all available parameters
- [Using the Messages API](/docs/v3/email/messages/) for search, modification, and deletion
- [Threads](/docs/v3/email/threads/) to group related messages into conversations
- [Search best practices](/docs/dev-guide/best-practices/search/) for advanced search with `search_query_native` across providers
- [Webhooks](/docs/v3/notifications/) for real-time notifications instead of polling
- [Yahoo authentication guide](/docs/provider-guides/yahoo-authentication/) for full Yahoo setup including OAuth and IMAP options
- [IMAP provider guide](/docs/provider-guides/imap/) for general IMAP configuration and behavior