Rate Limit Exceeded for NFT API

We believe that we are incorrectly being throttled and that the limits being returned to us in the error response are incorrect. We are paying for the pro plan and our code makes a series of requests to the GetNFTOwners endpoint via Moralis SDK (Moralis.Web3API.token.getNFTOwners). We are seeing the following in our logs:

2022-04-07T18:45:12.025Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making first Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544
2022-04-07T18:45:12.618Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 0
2022-04-07T18:45:13.155Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 1
2022-04-07T18:45:13.616Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 2
2022-04-07T18:45:14.441Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 3
2022-04-07T18:45:14.956Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 4
2022-04-07T18:45:15.463Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 5
2022-04-07T18:45:15.897Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 6
2022-04-07T18:45:17.825Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 7
2022-04-07T18:45:18.858Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 8
2022-04-07T18:45:19.456Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 9
2022-04-07T18:45:19.828Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	INFO	Making Moralis API request for contract 0xED5AF388653567Af2F388E6224dC7C4b3241C544 and page number 10
2022-04-07T18:45:19.860Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	ERROR	There was an error getting nft owner data from Moralis for 0xED5AF388653567Af2F388E6224dC7C4b3241C544 at cursor eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3aGVyZSI6eyJ0b2tlbl9hZGRyZXNzIjoiMHhlZDVhZjM4ODY1MzU2N2FmMmYzODhlNjIyNGRjN2M0YjMyNDFjNTQ0In0sImxpbWl0Ijo1MDAsIm9mZnNldCI6NTUwMCwib3JkZXIiOltbInRyYW5zZmVyX2luZGV4IiwiREVTQyJdXSwicGFnZSI6MTEsImtleSI6IjE0MTM2NjUyLjM3NS41MDguMCIsImlhdCI6MTY0OTM1NzExMn0.6NgseufnuI6y41aeBgaxh8TE0mVVUSRcKOmiDTFNdiU
"2022-04-07T18:45:19.862Z	f25aa090-91ed-54e3-a8eb-fa59a285747e	ERROR	Error: This Moralis Server is rate-limited because of the plan restrictions. See the details about the current rate and throttle limits: {"x-rate-limit-limit":"60","x-rate-limit-remaining-ttl":"1","x-rate-limit-used":"75","x-rate-limit-remaining-ip-ttl":"1","x-rate-limit-ip-used":"75"}
    at Function.fetchFromApi (/var/task/index.js:1149:24447)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async lae._getMoralisSnapshot (/var/task/index.js:1396:1535)
    at async lae._getSnapshotFromMoralisPageRange (/var/task/index.js:1396:2720)
    at async /var/task/index.js:1396:3247
    at async Promise.all (index 0)
    at async _Xe (/var/task/index.js:1396:3404)
    at async Runtime.b$0 [as handler] (/var/task/index.js:1396:4305)"

If I am not mistaken, the pro plan should let us make up to 60 requests per second (12 requests for the GetNFTOwners endpoint since it costs 5 requests). From our logs, we are well under that limit. And we are using the cursor param for making these requests. Below is our code that makes a single request:

  _getMoralisData = async (callingCursor = '', contractAddress: string) => {
    let response;
    try {
      response = await Moralis.Web3API.token.getNFTOwners({
        address: contractAddress,
        chain: 'eth',
        format: 'decimal',
        cursor: callingCursor,
      });
    } catch (e) {
      console.error(`There was an error getting nft owner data from Moralis for ${contractAddress} at cursor ${callingCursor}`);
      console.error(e);
    }
    const { page, status, cursor, result } = response;
    ....
    return { cursor, page }
}

And below is our code that makes a series of requests:

    let { cursor, page } = await this._getMoralisData(undefined, contractAddress);
    while (cursor !== '' && page !== undefined && page < stopPage - 1) {
      console.info(`Making Moralis API request for contract ${contractAddress} and page number ${page}`);
      const { cursor: newCursor, page: newPage } = await this._getMoralisData(cursor, contractAddress);
      page = newPage;
      cursor = newCursor;
    }

Any help here would be greatly appreciated since this throttling is significantly degrading our product experience.

1 Like

what happens is that an equivalent of high offset limit is applied here, with a cap on 25 requests towards the limit:

page 0: 5 requests
page 1: 5 requests
page 2: 10 requests
page 3: 15 requests
page 4: 20 requests
page 5: 25 requests
page 6: 25 requests
…
page 10: 25 requests

Got it. So just to make sure I understand correctly, some of the requests being made count for 25 requests (not 5). Is that correct? I have two follow up questions:

  1. If that’s the case, why is it suggested to use the cursor param in rate limited situations if it’s the same outcome as offset? For example, this post recommends using the cursor param to avoid the offset rate limit.
  2. Do you have any insight into why the rate limit behavior is inconsistent? I have previously not been rate limited when having made many more requests at once.

This is a temporary change that was made few days ago and we expect to get back to 5 per query for cursor after we do some improvements in our backend in the near future.

Do you have a rough idea of when we can expect cursor to go back to 5 per query?

It could be days to weeks. You can ask again in one week in case that it is not changed by that time.