How do I get the DOM from a webpage with Chrome Extension Manifest v3?

I’m making a chrome extension to gather data from a webpage. When I try to use document.querySelectorAll() it gets the DOM from the popup, not the current webpage. I tried using chrome’s messaging system to request and send back the HTML but it doesn’t work and gives me errors.

Here’s the important files:

manifest.json

{
  "name": "Name",
  "description": "Description",
  "version": "1.0",
  "manifest_version": 3,
  "permissions": ["storage", "activeTab", "scripting", "tabs"],
  "host_permissions": [
    "*://*.website.com/*"
  ],
  "content_scripts": [
    {
      "matches": ["*://*.website.com/*"],
      "js": ["content_script.js"]
    }
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "32": "/images/icon.png"
    }
  },
  "icons": {
    "32": "/images/icon.png"
  }
}

popup.js (runs inside popup.html)

function fetchData() {
  chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
    chrome.tabs.sendMessage(tabs[0].id, {greeting: "fetchData"}, (response) => {
      console.log(response);
    });
  });
}

content_script.js

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.greeting === "fetchData") {
      sendResponse(document.querySelectorAll(".class"));
    }
  }
);

The error I get from the message sending is “Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.”

When I turn the NodeList to an array, there are no console errors, but it returns a list of “[object Object]”.

Please let me know if there’s a way to do this. I’m just using vanilla js.