Minted ERC721 NFTs not displaying on OpenSea testnet

Problems with NFT visibility on OpenSea testnet

I’ve successfully deployed my code on the Rinkeby network, and it functions as expected. However, the images and descriptions of my NFTs aren’t visible on the OpenSea testnet. When I checked the validation URL, it returned Valid: "false".

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract MyCollection is ERC721URIStorage, Ownable {
    using Counters for Counters.Counter;
    using Strings for uint256;

    Counters.Counter private _tokenCounter;

    event NewNFTMinted(address owner, uint256 tokenId);

    uint256 public presalePrice = 0.01 ether;
    uint256 public publicSalePrice = 0.02 ether;
    uint256 public maxSupply = 10000;
    uint256 public maxMintablePerUser = 10;

    string public baseMetadataURI;
    string public unexposedMetadataURI;

    bool public mintingPaused = false;
    bool public isRevealed = true;

    address payable public admin = payable(0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2);

    constructor(string memory name, string memory symbol, string memory initialBaseURI, string memory hiddenURI) 
        ERC721(name, symbol) {
        setBaseURI(initialBaseURI);
        setUnvealedURI(hiddenURI);
    }

    function setBaseURI(string memory newBaseURI) public onlyOwner {
        baseMetadataURI = newBaseURI;
    }

    function mintNFT() public payable {
        uint256 tokenId = _tokenCounter.current();
        require(!mintingPaused, "Minting is currently paused");
        require(msg.value >= publicSalePrice, string(abi.encodePacked("Must send at least ", publicSalePrice.toString(), " ether to mint")));
        require(balanceOf(msg.sender) < maxMintablePerUser, "You can only mint a limited number of NFTs");

        payable(admin).transfer(msg.value);
        emit NewNFTMinted(msg.sender, tokenId);
        _safeMint(msg.sender, tokenId);
        _tokenCounter.increment();
    }

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "Token does not exist");

        if(!isRevealed) {
            return unexposedMetadataURI;
        }

        string memory baseURI = baseMetadataURI;
        return bytes(baseURI).length > 0 
            ? string(abi.encodePacked(baseURI, tokenId.toString()))
            : "";
    }
}

Here’s a link to one of the NFTs I minted: NFT Link

My IPFS CID is: ipfs://QmaoMZ19zhpC6T4id6jdBP1Qz5dQSmRZMkQZU7Zt8hyFNQ/

Has anyone else faced issues with OpenSea not displaying NFT metadata correctly? What could be causing the validation error?

Had the same headache with NFT metadata not showing on OpenSea testnet. Usually it’s the metadata JSON structure, not your contract code. First - visit your tokenURI directly (the full IPFS link). Does it return properly formatted JSON? You need the exact field names OpenSea wants: “name”, “description”, “image”, etc. Small typos or missing fields will break validation. Another gotcha is the image field in your metadata. If you’re pointing to IPFS images, make sure those files are actually accessible and the URLs work. Sometimes the metadata JSON loads fine but the referenced image is broken. OpenSea’s testnet indexing is painfully slow and unreliable. I’ve had NFTs take 2-3 days to show up properly even when everything was right. Try the “Refresh metadata” button on the NFT page, though it doesn’t always work immediately. Test your metadata with a JSON validator first, then check if you can access both the metadata and image files directly through IPFS gateways before messing with the contract.

Interesting issue! I’ve seen this a few times and it’s frustrating when everything works on your end but OpenSea won’t cooperate.

When you say your IPFS CID ends with /, are your metadata files structured correctly in that directory? Does ipfs://QmaoMZ19zhpC6T4id6jdBP1Qz5dQSmRZMkQZU7Zt8hyFNQ/0 return valid JSON when you access it directly?

You’re using Rinkeby - isn’t that network deprecated? OpenSea moved to Goerli for testnet stuff. That might be causing your validation issues.

Have you checked what your tokenURI function returns for token 0? Call it directly on Etherscan to see the exact string. Sometimes there are subtle formatting issues that break metadata even though the contract deploys fine.

How long ago did you mint these? OpenSea’s indexing takes forever on testnets - hours or even days. Their refresh metadata button doesn’t always work either, which is super annoying.

What happens when you paste that full tokenURI into your browser? Does it load proper JSON with image and description fields?

rinkeby’s been dead since late 2022 - that’s why opensea validation is failing. ethereum foundation killed it and opensea dropped support. you’ll need to redeploy on goerli or sepolia instead. your contract code looks good, but wrong network means no metadata on opensea.