Skip to main content

Command Palette

Search for a command to run...

How to Download SharePoint Recycle Bin as a CSV (No PowerShell Needed)

Dealing with the SharePoint Recycle Bin can be a hassle, especially when you need to audit its contents without PowerShell or admin access.

Updated
6 min read

Auditing the SharePoint Recycle Bin is difficult without PowerShell or administrative permissions. This guide offers a simple, non-destructive method to download a complete list of deleted items as a CSV, using just a small JavaScript code snippet in your browser's developer console.

This method is perfect for site owners or users with "Read" permissions who need a quick report of what's been deleted.

What You'll Need

  • A web browser: Chrome, Edge, or Firefox.

  • Access to your SharePoint site: You must be logged in with sufficient permissions to view the Recycle Bin.

  • The JavaScript code snippet: Provided below.

Step 1: Navigate to the SharePoint Recycle Bin

First, open your web browser and go to your SharePoint site's Recycle Bin. You can usually find this by going to Site Contents and clicking Recycle Bin at the top right of the page.

Your URL will look something like this: https://yourdomain.sharepoint.com/sites/<YourSite>/_layouts/15/RecycleBin.aspx

Step 2: Open the Developer Console (F12)

Now, we need to access the browser's developer tools. This is where we'll paste and run our code.

  • On Windows, press F12 or Ctrl + Shift + I.

  • On macOS, press Cmd + Option + I.

This will open the Developer Tools panel. Click on the Console tab.

Step 3: Enable Paste in the Console

For security reasons, some browsers (like Chrome and Edge) will prevent you from pasting code directly into the console. You'll see a warning message like "Do not paste code here unless you understand what you're doing."

To bypass this, you'll need to type allow pasting or a similar command into the console and hit Enter. Follow the specific instructions provided in the warning message to enable pasting.

Step 4: Paste and Customize the Code

Copy the following JavaScript code snippet. This script is designed to page through the SharePoint API, retrieve all items from the Recycle Bin, and then automatically compile and download a CSV file.

async function getAllRecycleBinItems() {
  // ⚙️ USER CONFIGURATION: Update these variables for your specific needs
  const siteUrl = "https://yourOrg.sharepoint.com/sites/accounting"; // Your SharePoint site URL
  const rowLimit = 5000; // Number of items to fetch per API call (max 5000)
  const itemState = 1; // 1 for first-stage recycle bin, 2 for second-stage

  // 🤖 DO NOT EDIT THE CODE BELOW THIS LINE
  let all = []; // Array to store all collected Recycle Bin items
  let keepOnRunning = true;
  let lastRecordId = null; // Used for paging: ID of the last item in the previous result set
  let lastRecordTitle = null; // Used for paging: Title of the last item
  let lastRecordDeletedDate = null; // Used for paging: DeletedDate of the last item
  let currentPage = 1; // Counter for logging progress

  try {
    // Construct URL for the first page fetch
    let url = `${siteUrl}/_api/web/GetRecycleBinItemsByQueryInfo(rowLimit=@a1,isAscending=@a2,itemState=@a3,orderby=@a4,ShowOnlyMyItems=@a5)?@a1='${rowLimit}'&@a2=false&@a3=${itemState}&@a4=3&@a5=false`;

    console.log(`Starting to retrieve items from the Recycle Bin at: ${siteUrl}`);
    const resp = await fetch(url, {
      headers: { "Accept": "application/json;odata=verbose" }
    });

    if (!resp.ok) {
      // Check for a non-200 HTTP status code and throw an error
      throw new Error(`HTTP error! status: ${resp.status}`);
    }

    const data = await resp.json();
    // Navigate the JSON response to find the results array
    const page = data?.d?.GetRecycleBinItemsByQueryInfo || data?.d;
    let results = page?.results || [];

    if (results.length > 0) {
      // Map the results to a new array with only the required properties
      const selected = results.map(item => ({
        Title: item.Title,
        DirName: item.DirName,
        DeletedByName: item.DeletedByName,
        DeletedDate: item.DeletedDate,
        ItemType: item.ItemType,
        Size: item.Size
      }));
      all.push(...selected); // Add the mapped items to the main array
    }

    console.log(`✅ Page ${currentPage} fetched. Retrieved ${results.length} items. Total so far: ${all.length}.`);

    // Check if there are more pages to fetch
    if (results.length === rowLimit) {
      // Get the last item's details for the next page's URL
      lastRecordId = results[rowLimit - 1].Id;
      // Replace single quotes in the title to prevent URL errors
      lastRecordTitle = results[rowLimit - 1].Title.replace(/'/g, "%27");
      lastRecordDeletedDate = results[rowLimit - 1].DeletedDate.replace("Z", "");
    } else {
      keepOnRunning = false; // No more pages to fetch
    }

    // Loop to fetch all subsequent pages
    while (keepOnRunning) {
      currentPage++;
      // Encode the paging values for the URL
      const encodedId = encodeURIComponent(lastRecordId);
      const encodedTitle = encodeURIComponent(lastRecordTitle);
      const encodedDate = encodeURIComponent(lastRecordDeletedDate);
      // Construct the PagingInfo string
      const pagingInfo = `id=${encodedId}&title=${encodedTitle}&searchValue=${encodedDate}`;

      // Construct URL for subsequent pages, including the encoded PagingInfo
      let url2 = `${siteUrl}/_api/web/GetRecycleBinItemsByQueryInfo(rowLimit=@a1,isAscending=@a2,itemState=@a3,orderby=@a4,pagingInfo=@a5,ShowOnlyMyItems=@a6)?@a1='${rowLimit}'&@a2=false&@a3=${itemState}&@a4=3&@a5='${encodeURIComponent(pagingInfo)}'&@a6=false`;

      try {
        const resp2 = await fetch(url2, {
          headers: { "Accept": "application/json;odata=verbose" }
        });

        if (!resp2.ok) {
          throw new Error(`HTTP error! status: ${resp2.status}`);
        }

        const data2 = await resp2.json();
        const page2 = data2?.d?.GetRecycleBinItemsByQueryInfo || data2?.d;
        results = page2?.results || [];

        if (results.length > 0) {
          const selected = results.map(item => ({
            Title: item.Title,
            DirName: item.DirName,
            DeletedByName: item.DeletedByName,
            DeletedDate: item.DeletedDate,
            ItemType: item.ItemType,
            Size: item.Size
          }));
          all.push(...selected);
        }

        console.log(`✅ Page ${currentPage} fetched. Retrieved ${results.length} items. Total so far: ${all.length}.`);

        if (results.length === rowLimit) {
          lastRecordId = results[rowLimit - 1].Id;
          lastRecordTitle = results[rowLimit - 1].Title.replace(/'/g, "%27");
          lastRecordDeletedDate = results[rowLimit - 1].DeletedDate.replace("Z", "");
        } else {
          keepOnRunning = false;
        }

      } catch (error) {
        // Log the specific error for this page and stop the loop
        console.error(`❌ An error occurred during page ${currentPage} retrieval:`, error);
        keepOnRunning = false;
      }
    }

    console.log(`\n🎉 All items have been retrieved.`);
    console.log(`Final retrieved records count: ${all.length}.`);

    if (all.length > 0) {
      // Prepare data for CSV
      const headers = Object.keys(all[0]).join(",");
      const rows = all.map(obj =>
        // Format each value, handling commas and quotes within the data
        Object.values(obj).map(v => `"${String(v).replace(/"/g, '""')}"`).join(",")
      );
      const csv = [headers, ...rows].join("\n");

      // Trigger the browser to download the CSV file
      const blob = new Blob([csv], { type: "text/csv" });
      const link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = "RecycleBinItems.csv";
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);

      console.log(`⬇️ CSV downloaded with ${all.length} records.`);
    }

  } catch (error) {
    // Log any errors from the initial fetch or overall process
    console.error("❌ An error occurred:", error);
    console.log("Process terminated due to an error.");
  }
}
getAllRecycleBinItems();

Before pasting, you must customize the siteUrl variable at the top of the code to match your SharePoint site. For example, if your site is at https://yourcompany.sharepoint.com/sites/accounting, change the line to:

const siteUrl = "https://yourcompany.sharepoint.com/sites/accounting";

Step 5: Run the Code

After pasting the code, press Enter.

The script will immediately begin to run. You will see progress messages in the console, showing how many items have been fetched on each page. The process will continue automatically, retrieving pages of up to 5,000 items at a time.

Once the script has fetched all the items, you will see a final success message in the console.

Step 6: Download the CSV File

After the final message appears, your browser will automatically prompt you to save a file named RecycleBinItems.csv.

If your browser blocks the download, you may need to check your browser's download settings or a pop-up blocker. The console will also log a message, ⬇️ CSV downloaded..., confirming the action.

Open the downloaded file in a spreadsheet program like Microsoft Excel or Google Sheets to view all your SharePoint Recycle Bin items, including their titles, deletion dates, and who deleted them.

That's it! You've successfully exported your SharePoint Recycle Bin contents without needing any administrative tools or special software.

Conclusion

By using this straightforward JavaScript approach, you can efficiently bypass the typical limitations of SharePoint's user interface, which often hides important data behind multiple clicks and lacks an export function. This method empowers you to quickly generate an auditable record of all deleted files and items, providing valuable insights into a site's history and helping you manage its content more effectively. This technique demonstrates how a few lines of code can solve a common problem, offering a powerful alternative to complex administrative tools and saving you time.

Download SharePoint Recycle Bin Without PowerShell as CSV