Write scraped rows to .xlsx with pandas
The fastest path is pandas: collect your scraped records as a list of dictionaries and call DataFrame.to_excel("out.xlsx", index=False). pandas uses openpyxl under the hood as the .xlsx engine, so pip install pandas openpyxl is all you need.
The key idea is that a scraping API gives you JSON, and JSON maps cleanly onto rows and columns. Each dictionary becomes one Excel row; the dictionary keys become the header row. For a product table you might collect {"name": ..., "price": ..., "url": ...} per item, append each to a list, then hand the whole list to pd.DataFrame(rows). Setting index=False keeps Excel from adding an extra unnamed column. To split data across multiple sheets in one workbook, open a pd.ExcelWriter and call to_excel once per sheet with different sheet_name values. If a page already exposes a clean HTML <table>, pandas.read_html() can pull every table into DataFrames in a single line.
When you need openpyxl directly
Use openpyxl directly when you want Excel-specific formatting, multiple sheets built incrementally, or to append rows to an existing workbook without reloading everything into memory. pandas is great for a clean one-shot dump; openpyxl gives you per-cell control.
With openpyxl you create a Workbook, grab the active sheet, write a header with ws.append([...]), then loop your scraped records calling ws.append([row["name"], row["price"]]) for each. From there you can bold the header (cell.font = Font(bold=True)), set column widths (ws.column_dimensions["A"].width = 40), freeze the top row (ws.freeze_panes = "A2"), or add a new sheet per category with wb.create_sheet. This streaming append style also lets you handle pagination: keep appending rows as you fetch each page, then call wb.save() once at the end so the entire crawl lands in a single workbook.
No-code route, blocks, and empty tables
If you would rather not write Excel code, write the rows to a CSV file and open it in Excel via Data > From Text/CSV; if your table comes back empty, the page is rendering with JavaScript and needs a real browser fetch first.
One Excel-specific CSV gotcha: write the file as UTF-8 with a BOM so accented characters and currency symbols display correctly. In Python that is open("out.csv", "w", newline="", encoding="utf-8-sig") with csv.DictWriter, or simply df.to_csv("out.csv", index=False, encoding="utf-8-sig"). CSV does flatten structure, so nested or list-valued fields get stringified; prefer .xlsx for nested data. The other common failure is an empty file because the page renders client-side or returns a blocking response. Fetching through a scraping API that renders dynamic content and routes through residential proxies returns the fully rendered HTML or parsed JSON, which you then pass to pandas. For delimiters, escaping, and JSON output, see the sibling guide on exporting scraped data to CSV and JSON.
