Code Monkey home page Code Monkey logo

opensea-scraper's Introduction

Opensea Scraper

DISCLAIMER: You can get accurate realtime floor prices from this official opensea API endpoint: https://api.opensea.io/api/v1/collection/{slug}/stats:

const axios = require("axios");

async function getFloorPrice(slug) {
  try {
    const url = `https://api.opensea.io/collection/${slug}/stats`;
    const response = await axios.get(url);
    return response.data.stats.floor_price;
  } catch (err) {
    console.log(err);
    return undefined;
  }
}

await getFloorPrice("lostpoets");
await getFloorPrice("treeverse");
await getFloorPrice("cool-cats-nft");

If you need floor prices, please use the official API (see above ๐Ÿ‘†๐Ÿ‘†๐Ÿ‘†). This scraper still can be used to scrape additional information about offers (tokenId, name, tokenContractAddress and offerUrl) as well as the ranking.

Install

npm install opensea-scraper

Usage

โ„น slug is the human readable identifier that opensea uses to identify a collection. It can be extracted from the URL: https://opensea.io/collection/{slug} slug

โ„น options is an object with the following keys

  • debug [Boolean] launches chromium locally, omits headless mode (default: false)
  • logs [Boolean]: display logs in the console (default: false)
  • sort [Boolean]: sorts the offers by lowest to highest (default: true)
  • additionalWait [Number]: time to wait (in milliseconds) after page was loaded before the scraping starts (default: 0)
  • browserInstance [PuppeteerBrowser]: bring your own browser instance for more control
const OpenseaScraper = require("opensea-scraper");

// which nft project to scrape?
const slug = "cool-cats-nft";

// options
const options = {
  debug: false,
  logs: false,
  sort: true,
  additionalWait: 0,
  browserInstance: undefined,
}

// get basic info (from the opensea API)
const basicInfo = await OpenseaScraper.basicInfo(slug);

// get offers from opensea. Each offer includes the 
// floor price, tokenName, tokenId, tokenContractAddress
// and offerUrl
// scrapes only the first 20 offers from opensea.
let result = await OpenseaScraper.offers(slug, options);
console.dir(result, {depth: null}); // result object contains keys `stats` and `offers`

// get offers from opensea using a custom link
// Opensea supports encoding filtering in the URL so 
// this method is helpful for getting a specific asset 
// (for example floor price for a deadfellaz with  
// a purple fur trait)
let url = "https://opensea.io/collection/deadfellaz?search[sortAscending]=true&search[sortBy]=PRICE&search[stringTraits][0][name]=Body&search[stringTraits][0][values][0]=Purple%20Fur&search[toggles][0]=BUY_NOW";
result = await OpenseaScraper.offersByUrl(url, options);
// result object contains keys `stats` and `offers`
console.dir(result, {depth: null}); 

// DISCLAIMER: FUNCTION `offersByScrolling`
// IS CURRENTLY NOT WORKING (!!!) see [issue#36](https://github.com/dcts/opensea-scraper/issues/36)
// get offersByScrolling from opensea. This is an 
// alternative method to get the same data as with
// the function `offers`, with the only difference 
// that the data is here scraped actively by scrolling 
// through the page. This method is not as efficient
// as the `offers` method, but it can scrape more 
// than 20 offers. You could even scrape a whole 
// collection with ~10k spots (this is not recommended 
// though).
// IMPORTANT: if you need less than 20 offers, 
// please use the function `offers()` instead
let resultSize = 40; 
result = await OpenseaScraper.offersByScrolling(slug, resultSize, options);
// result object contains keys `stats` and `offers`
console.dir(result, {depth: null}); 

// DISCLAIMER: FUNCTION `offersByScrollingByUrl`
// IS CURRENTLY NOT WORKING (!!!) see [issue#36](https://github.com/dcts/opensea-scraper/issues/36)
// get offersByScrollingByUrl from opensea using a 
// custom link instead of the slug. the same logic 
// applies as in `offersByScrolling()`
// Opensea supports encoding filtering in the URL so 
// this method is helpful for getting a specific asset 
// (for example floor price for a deadfellaz with  
// a purple fur trait)
// IMPORTANT: if you need less than 20 offers, 
// please use the function `offersByUrl()` instead
url = "https://opensea.io/collection/deadfellaz?search[sortAscending]=true&search[sortBy]=PRICE&search[stringTraits][0][name]=Body&search[stringTraits][0][values][0]=Purple%20Fur&search[toggles][0]=BUY_NOW";
resultSize = 40;
result = await OpenseaScraper.offersByScrollingByUrl(url, resultSize, options);
// result object contains keys `stats` and `offers`
console.dir(result, {depth: null}); 

// scrape all slugs, names and ranks from the top collections from the rankings page
// "type" is one of the following:
//   "24h": ranking of last 24 hours: https://opensea.io/rankings?sortBy=one_day_volume
//   "7d": ranking of last 7 days: https://opensea.io/rankings?sortBy=seven_day_volume
//   "30d": ranking of last 30 days: https://opensea.io/rankings?sortBy=thirty_day_volume
//   "total": scrapes all time ranking: https://opensea.io/rankings?sortBy=total_volume
// "chain" is one of the following: "ethereum", "matic", "klaytn", "solana"
//    if chain is unset, all chains will be selected by default
const type = "24h"; // possible values: "24h", "7d", "30d", "total"
const chain = "solana";
const ranking = await OpenseaScraper.rankings(type, chain, options);

Debugging

To investigate an issue turn on logs and debug mode (debug: true and logs: true):

const result = await OpenseaScraper.offers("treeverse", {
  debug: true,
  logs: true
});

Bring your own puppeteer

if you want to customize the settings for your puppeteer instance you can add your own puppeteer browser instance in the options. ๐Ÿšง IMPORTANT: I recommend using stealth plugin as otherwise you most likely won't be able to scrape opensea. If you find a way without using the stealth plugin please report in the form of an issue!

const puppeteer = require('puppeteer-extra');
// add stealth plugin and use defaults (all evasion techniques)
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());

const myPuppeteerInstance = await puppeteer.launch(myCustomSettings);

const result = await OpenseaScraper.offer("cool-cats-nft", {
  browserInstance: myPuppeteerInstance
});

Demo

npm run demo

Run local console / REPL

To test the functions in an REPL node environment that has OpenseaScraper service preloaded simply run:

node --experimental-repl-await -i -e "$(< init-dev-env.js)"

I recommend saving an alias:

alias consl='node --experimental-repl-await -i -e "$(< init-dev-env.js)"';

Contribute

Open PR or issue if you would like to have more features added.

Donations ๐Ÿ™

Thanks for your support!
BTC: bc1qq5qn96ahlqjxfxz2n9l20kem8p9nsz5yzz93f7
ETH: 0x3e4503720Fb8f4559Ecf64BE792b3100722dE940

nftfloorprice.info ๐Ÿ””

Simple NFT floor price alerts. Easily track all your NFTs and receive realtime email alerts with: https://nftfloorprice.info

opensea-scraper's People

Contributors

androz2091 avatar dcts avatar jethro87 avatar robertistok avatar xfloki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

opensea-scraper's Issues

[FEATURE REQUEST] scrape collection activity

As collection offers just arrived and are not get by the API I would like to be able to scrape collection activity to check if there is collection offers.

Do you take new stuff on the roadmap or just maintaining it?

Code freezes when running `OpenseaScraper.rankings()`

If I try to run the script on Linux (computer in the same network) it stops right here without any errors like it's frozen. It works perfectly fine on Mac and it's the same code. It worked a week ago and nothing was changed.

โœ… === OpenseaScraper.rankings() ===
=== OpenseaScraper.rankings() ===
...fetching 1 pages (= top 100 collections)
...opening url: https://opensea.io/rankings?sortBy=one_day_volume
...๐Ÿšง waiting for cloudflare to resolve
...exposing helper functions through script tag
...scrolling to bottom and fetching collections.
-> freezes here <-

There are no errors. It seems like its stuck in an infinite loop


Edit: After a lot of investigation i finally found what causes the freezing:

If I change the url in the rankings.js from "https://opensea.io/rankings?sortBy=total_volume" to "https://opensea.io/rankings?sortBy=one_day_volume" the script freezes, it works perfectly with the total_volume though. Seven_day_volume does also cause freezing. It is weird because it also worked with one_day_volume a few days ago

Can't fetch anymore collections (Opensea cloudflare update)

Hey everybody,

I noticed that opensea increased the number of times it checked my browser when opening it.
I then noticed that the script can't fetch anymore collections.

โœ… === OpenseaScraper.rankings() ===
=== OpenseaScraper.rankings() ===
...fetching 1 pages (= top 100 collections)
...opening url: https://opensea.io/rankings?sortBy=one_day_volume
...๐Ÿšง waiting for cloudflare to resolve
...exposing helper functions through script tag
...scrolling to bottom and fetching collections.
...๐Ÿฅณ DONE. Total Collections fetched: 0
scraped 0 collections:

Is this the same for you guys? Does anyone have an idea on how to fix this?

Thanks

offersByScrolling() and offersByScrollingByUrl() does not work

Hey everyone so I have been trying to scrape some page from Opensea. And I have used the offersByScrollingByUrl() but I was unsuccessful.
When I use these methods offersByScrollingByUrl() even though I provide the resultSize it stop once it reaches the bottom of page.
and once it reaches the bottom it returns empty resuly.
{ offers: [], stats: { totalOffers: undefined } }

my code:
`const options = {
debug: false,
logs: true,
sort: false,
additionalWait: 0,
browserInstance: undefined,
};

(async () => {
try {
let resultSize=1
const urlWithFilters = 'https://opensea.io/collection/wilderness-to-blockchain-editions?search[sortAscending]=false&search[sortBy]=LAST_SALE_DATE&search[toggles][0]=BUY_NOW';
const res = await OpenseaScraper.offersByScrollingByUrl(urlWithFilters,resultSize, options);
OpenseaScraper.
// const res = await OpenseaScraper.offersByUrl(urlWithFilters,options)
console.log(res);
} catch (err) {
console.log(err);
}
})();`

Any help??
thanks
using the latest v 6.5.2.

adding testnet

Hey
What could be nice is adding testnet option to scrap opensea testnet website :)

Only grabs top 2 grids, would be awesome if it grabbed everything

I would like to be able to scrape all of the cards on a page for Id information, but I found that as currently implemented, this scraper only actually grabs the top 2-6 with this line in OpenseaScraper.js const cardsNodeList = document.querySelectorAll(".Asset--anchor");. This works great for finding the floor, but what if I wanted to grab all of the cards, would this be possible? I tried a couple other options like querySelectorAlling on '[role="gridcell"]' but ultimately found no improvement - would you have any ideas on why it isn't able to grab the whole page worth of cards? Thanks so much!

docs should warn that browserInstance requires stealth plugin

I need to provide a browserInstance as my code runs in an alpine docker container. I was having weird issues, like empty resultsets for offersByScrolling and an error for offers because a split on some part of the html could not be found...
I eventually found out that my browserInstance was detected by opensea, which was serving a warning page instead of the content and tripping opensea-scraper
Don't you thing the doc should have a warning note about browserInstance explaining that it needs to implement puppeteer-extra-plugin-stealth ?

[BUG] Cannot get any result for floor price

I cannot get any result for floor price from a NFT on opensea. I used the same code as before (it worked), but now it does not work. I would wonder - is it caused by opensea website upgrade? Thanks.

TODO: replace fetching of the floor price with new method

Theres a faster way of getting floor prices I just found. When you have a collection endpoint with query params (meaning filtering is enabled), opensea exposes a __wired__ variable to the window with a lot of information, also including the floor prices. Simply run:

Object.values(__wired__.records)
  .filter(o => o.__typename === "AssetQuantityType")
  .filter(o => o.quantityInEth)
  .map(o => o.quantity / 1000000000000000000);

Some Remarks

  • โœ… this does work on pages that have filtering enabled (BUY NOW). Example
  • โŒ does not work on the /collection/{slug} route without query params. example
  • this new method improves speed because you don't need to scroll
  • only the top 32 offers are availible, so if you need more than that you would still need to scroll

Leaving this here for the moment because inside the __wired__ variable there is a lot of information that I currently cannot make sense of. I think there might be more hidden such that we can maybe also find the tokenId or name in this object. If someone wants to do some digging feel free @Jethro87 @robertistok @Androz2091 .

I implemented a method in the branch alternative-method-to-get-floor-prices but not sure yet whether to replace the old way of scraping that data (through the cards), or leave both methods coexist so the developer can try both functions (not ideal) or implement a fallback machanism (try method 1, if it fails try method2).

const floorPrices = async (slug, mode = "headless") => {

Will leave open for discussion for now :)

New puppeteer launch for every call of the functions

Hello!

In case one would like to run the scraper in a worker, to check for example the offers for multiple projects asynchronously, the current solution would launch a new puppeteer instance for each call.

There are two solutions that came to my mind:

  1. Add the third argument, object named opts, to the functions, where users would be able to bring their own puppeteer instance. This is not the most elegant solution IMO, as it would be more complex for the caller.
  2. Export an OpenseaScraper class, that would need to be instantiated. In the constructor, we would launch a puppeteer instance and pass it down to the functions, as described in the first point. We could export both the functions as it is now and the new class.

What do you think? I think it would be valuable to have this functionality, as it would add lots of efficiencies when the functions are called one after another.

I'd be happy to submit a PR for this!

scrapping owner address from a collection

Is it possible to scrapper the owner address using this tool from any specific project

I know from smart contract we can easily do that.

But collections which I am at is created using opensea store contract

[BUG] Cannot get price

Hi,

I used two scripts below for getting prices of nfts, but all failed. I remembered that I can get prices by using function "offers" or "offersByUrl" before, but they do not work now.
Script 1:
let result_testnet = await OpenseaScraper.offersByUrl("https://testnets.opensea.io/collection/doodles-officias", options); console.dir(result_testnet, {depth: null}); // result object contains keys stats and offers
image

Script 2:
let result = await OpenseaScraper.offers(nft, options); console.dir(result, {depth: null}); // result object contains keys stats and offers
image

Any suggestions for that? Thanks.

OpenseaScraper.rankings

image
image
This functionality no longer works, getting an axios error from this function alone. It responds with error code 404 which is file not found.

Buggy If Multiple Currencies

Some slugs, like lostpoets would have multiple currencies.

The floor for example is at .969 ETH as of this writing.
https://opensea.io/collection/lostpoets

The first listing is selling it for 160 "ASH"

image

When this scraper scrapes, it returns 160 as floor, instead of .969.

One of 2 ways to handle I think: kill outliers in first few floor listings and take the minimum. Or just convert whatever currency to ETH.

All Functions return Promise { <pending> }

Hey,

if I try to use any function it returns "Promise pending".

I also removed the "await" from the functions because I get this error if i keep it:

const ranking = await OpenseaScraper.rankings(nbrOfPages, options);
                ^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules

I would appreciate your help :)

Code used:

const OpenseaScraper = require("opensea-scraper");

// options
const options = {
  debug: false,
  logs: false,
  sort: true,
  browserInstance: undefined,
}

const nbrOfPages = 1;
const ranking =  OpenseaScraper.rankings(nbrOfPages, options);
console.dir(ranking)

[BUG] `offersByScrolling()` and `offersByScrollingByUrl()` not properly working

I noticed that the function offersByScrolling() and offersByScrollingByUrl() is not working properly. Most of the offers are not scraped (a lot of them are skipped for some reason, approximately 75% of the offers are not saved). This leads to the function being stuck for a long time, as it takes a lot longer to scrape the desired amount of offers when 75% of the offers are not scraped.

Accurate floor price now available via API

Hi- OpenSea employee here. We've added the floor_price to the /stats endpoint, and this should reflect the same up-to-date price as on our website:

GET /api/v1/collection/cool-cats-nft/stats
HTTP 200 OK
Allow: OPTIONS, GET
Content-Type: application/json
Vary: Accept

{
    "stats": {
        "one_day_volume": 227.8588,
        "one_day_change": 0.7904841231799217,
        "one_day_sales": 34.0,
        "one_day_average_price": 6.701729411764706,
        "seven_day_volume": 1070.25705670901,
        "seven_day_change": -0.42636165444007446,
        "seven_day_sales": 140.0,
        "seven_day_average_price": 7.6446932622072135,
        "thirty_day_volume": 8349.7626205981,
        "thirty_day_change": -0.546823704869074,
        "thirty_day_sales": 761.0,
        "thirty_day_average_price": 10.97209279973469,
        "total_volume": 52723.9290518944,
        "total_sales": 22636.0,
        "total_supply": 9933.0,
        "count": 9933.0,
        "num_owners": 4940,
        "average_price": 2.329206973488885,
        "num_reports": 1,
        "market_cap": 75934.73817350426,
        "floor_price": 5.45
    }
}

https://api.opensea.io/api/v1/collection/cool-cats-nft/stats
https://twitter.com/apiopensea/status/1455918328397144069

Not working when deployed (Heroku)

This is not working for me when I deploy the app on heroku but working fine in local.
Is that the same for you?

image

Wanna use this package because a collection can have different categories of NFT and OpeanSea's API don't provide to filter by trait

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.