How to scrape pharmaceutical and biotech data from PDR using the Minexa API
- Minexa.ai

- 22 hours ago
- 5 min read
Drug label data sitting behind a browser is useless to a pipeline. This guide shows how to pull structured pharmaceutical listings from PDR at scale using the Minexa API, covering every field worth knowing and the exact request body to get started.
What PDR exposes at the browse-by-drug-name endpoint
PDR (pdr.net) is a clinical reference platform used across healthcare and biotech. Its drug browse page at pdr.net/browse-by-drug-name lists thousands of drug entries alphabetically, each carrying a brand name, active ingredient, document availability flags, versioned label identifiers, and direct links to Drug Summary and Full Prescribing Information pages. For pharmaceutical researchers, regulatory teams, or biotech data pipelines, this is a dense, structured source that is worth extracting systematically rather than browsing manually.
Watch the full extraction walkthrough
The video below covers the complete workflow from opening the Minexa Chrome extension on the PDR page through to a running API call returning structured drug data.
Step 1: Open the Minexa extension on the PDR page
Navigate to pdr.net/browse-by-drug-name in Chrome, then open the Minexa extension. The extension detects the page is loaded and presents the starting prompt.
Click "I'm on the right page" to confirm the target URL. Minexa registers the page context and moves to the next configuration step.
Step 2: Confirm pagination handling
PDR's drug list spans many pages. The extension surfaces the detected pagination controls so you can verify the next-page logic before committing to a scraping mode. Review the detected pagination and click Continue.
After confirming pagination, choose whether to scrape the listing only or the listing plus each drug's linked detail pages. For most pharmaceutical data pipelines, the listing alone returns enough structured fields to be immediately useful.
Step 3: Select the data container and create the scraper
Choose your scraping scenario (simple or advanced), then hover over the HTML element that wraps the full drug listing block. Minexa highlights the container automatically once it detects the repeating list structure.
Click Create Scraper. Within a couple of minutes, Minexa identifies all data points within the container and assigns column names. You can page through each extracted field using the prev/next navigation.
Step 4: Get the API request and Python code
Click API Request in the top right of the extension. This opens the pre-generated request body with your scraper_id already populated, along with a ready-to-run Python snippet you can copy directly into your pipeline.
Complete the configuration to save the scraping job, then find it listed in your dashboard with a Run button ready.
API reference: request body for PDR extraction
Below is the request structure to call after training your scraper. Replace scraper_id with the value generated by the extension and populate urls with the PDR pages you want to process.
import requests
url = "https://api.minexa.ai/data/"
api_key = "YOUR_API_KEY"
data = {
"batches": [{
"scraper_id": 4712,
"columns": ["top_40"],
"urls": [
"https://www.pdr.net/browse-by-drug-name"
],
"scraping": {
"js_render": True,
"timeout": 30,
"js_code": [
{"wait_time": 2},
{"page_init": True},
{"wait_time": 4}
],
"proxy": "verified",
"retry": 3
}
}],
"threads": 5
}
headers = {"Content-Type": "application/json", "api-key": api_key}
response = requests.post(url, json=data, headers=headers)
print(response.json())
The columns parameter accepts "top_N" notation to return the top N ranked fields automatically, or an explicit list of column names if you want to pin specific fields. Both approaches cost the same.
Field reference: what each column contains
drug_name — The full brand or generic name as it appears on the listing, for example '0.25% Acetic Acid' or 'Abilify Maintena'. This is the primary display label per row.
additional_info — The active ingredient in parentheses, for example '(aripiprazole)' or '(paclitaxel protein-bound)'. Useful for mapping brand names to their generic equivalents programmatically.
document_type — Returns a structured array of typed objects. Each object carries a value (the link text such as 'Drug Summary' or 'Full Prescribing Information'), a tag, an attribute (null for text nodes, 'href' for link targets), and a type field. To extract only the href values: [x['value'] for x in row['document_type'] if x['attribute'] == 'href']. This gives you the direct paths to both the summary and prescribing info pages per drug.
content_summary — A parallel array to document_type but containing only the text-node objects, with no href entries. It surfaces which document types are available for a given listing without the link targets. Useful for quick availability checks before fetching detail pages.
drug_summary_href — The relative path to the Drug Summary page, for example /drug-summary/?drugLabelId=103. Empty string when no Drug Summary exists for the listing.
prescribing_info_link — The relative path to the Full Prescribing Information page. Present on most listings; empty on entries where only a summary is available.
drug_info_href — The relative path to the general drug information page. Always present per listing and doubles as the destination for Drug Alert and Drug Resources links when those document types appear.
related_link — An optional third document category label. Values observed include 'Drug Alert', 'Drug Resources', or an empty string. When non-empty, the corresponding href is found inside the document_type array at the third link object. This field lets you filter listings with active safety alerts without parsing the full document_type array.
label_version_id — A compound string joining the numeric drug label ID and the version number with an underscore, for example '3096_17' or '663_15'. This encodes both the label identity and its revision state in a single field, useful for detecting when a label has been updated between scraping runs.
version_number — The plain version number as a string, for example '25' or '10'. Tracking this field across runs lets you identify which drug labels have been revised since your last extraction.
is_hidden_label — A boolean string ('true' or 'false') that indicates whether the Drug Summary link is suppressed for a given listing. When 'false', the listing shows only Full Prescribing Information, as with dietary supplement entries. Filtering on this field separates prescription drug entries from supplement or OTC listings.
section_title — The primary document type label rendered per listing, either 'Drug Summary' or 'Full Prescribing Information'. Mirrors the first entry in content_summary.
object_id and posinset — Internal DOM identifiers. object_id is a long numeric string unique per listing. posinset reflects the ordinal position of the entry within the current page's list, resetting to 1 on each new page. Use meta__result_identifier from the API response for a globally unique row index across all pages.
Sample output: three drug records
[
{
"drug_name": "Abelcet",
"additional_info": "(amphotericin B lipid complex)",
"drug_summary_href": "/drug-summary/?drugLabelId=539",
"prescribing_info_link": "/full-prescribing-information/hl/?druglabelid=539",
"related_link": "Drug Alert",
"label_version_id": "539_11",
"version_number": "11",
"is_hidden_label": "true",
"section_title": "Drug Summary"
},
{
"drug_name": "Abilify",
"additional_info": "(aripiprazole)",
"drug_summary_href": "/drug-summary/?drugLabelId=103",
"prescribing_info_link": "/full-prescribing-information/hl/?druglabelid=103",
"related_link": "Drug Resources",
"label_version_id": "103_25",
"version_number": "25",
"is_hidden_label": "true",
"section_title": "Drug Summary"
},
{
"drug_name": "4Life Transfer Factor Tri-Factor Formula",
"additional_info": "(dietary supplement)",
"drug_summary_href": "",
"prescribing_info_link": "",
"related_link": "",
"label_version_id": "159_10",
"version_number": "10",
"is_hidden_label": "false",
"section_title": "Full Prescribing Information"
}
]
Exporting and next steps
Once the job finishes, results are available as Excel or JSON directly from the Minexa dashboard. The Python script above writes checkpoint files at each iteration, so partial results are saved even on long multi-page runs.
If you want to run this on a recurring basis, set up a cron job on your side and call https://api.minexa.ai/data/ with updated URL lists on each run. The scraper_id stays constant as long as PDR does not change its page structure. If it does, retraining via the extension takes a few minutes and produces a new scraper_id to swap into your request body.
For a related example using the Minexa API on another healthcare data source, see: How to scrape jobs data from Apna using the Minexa.ai API.

Comments