Drogasil Brazil Pharmacy, Health & Beauty Scraper
Pricing
from $1.50 / 1,000 product results
Drogasil Brazil Pharmacy, Health & Beauty Scraper
Scrape Drogasil (drogasil.com.br) medicines, health and beauty products by keyword, catalogue section or pasted link. Returns EAN, brand, price in BRL, discount, multi-buy price, stock, images, variants and the regulatory block. Incremental mode tracks daily changes.
Pricing
from $1.50 / 1,000 product results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
15 hours ago
Last modified
Categories
Share
Scrape the full product catalogue of drogasil.com.br, one of Brazil's largest pharmacy chains: medicines, vitamins and supplements, health devices, beauty, daily care, baby and pet.
Search by keyword, browse a whole catalogue section, or paste links. Every record comes back flat, with the barcode, the current and pre-discount price in BRL, the multi-buy ("leve mais por menos") offer, live stock, images, per-variant rows, and the full Brazilian pharmacy regulatory block.
What you get
Always (listing fields, no extra reads)
| Field | Description |
|---|---|
productId, sku | The store's own product code |
name, brand | Product title and brand |
url | Canonical product address (tracking parameters stripped) |
image, images | Cover image and gallery |
price, currency | Current price, always BRL |
packSize | Pack size as the store states it (10 Comprimidos, 3g, 100ml) |
prescriptionRequired | Whether a prescription is needed |
isGenericMedicine | Generic (genérico) medicine flag |
isKit | Bundled multi-product kit |
requiresRefrigeration | Cold-chain product (termolábil) |
soldBy | drogasil (the pharmacy's own stock) or marketplace (a partner seller) |
categories, categoryPath | Category trail, as a list and as one string |
productGroup | The store's own product grouping (MEDICAMENTO, OTC, PERFUMARIA, ...) |
pharmaceuticalForm | Dosage form when the store publishes it on the card |
drugClassificationCode | The store's own medicine classification code |
badges | Promotional labels shown on the card |
variantCount, variantAttributes | How many variants exist, and this one's option values |
isSponsored | The row was a sponsored placement in a keyword search |
searchMode, scrapedAt | Which route found the product, and when |
With Fetch product details on (one extra read per product, billed once)
| Field | Description |
|---|---|
ean | Barcode / GTIN-13 |
originalPrice, discountPercent, onSale | Pre-discount price and the reduction |
multiBuyUnitPrice, multiBuyMinQuantity | The "leve mais por menos" offer: buy N or more, pay this per unit |
pixPrice, pixDiscountPercent | The instant-payment (Pix) price and its extra discount |
installments | Instalment plan rows (count, amount) |
stockQuantity, inStock | Live stock the store reports for the product |
images | The full media gallery, in the store's own order |
description, shortDescription, longDescription | Product copy, flattened to plain text |
usageInstructions | The store's detailed product description line |
activeIngredient | Active ingredient (princípio ativo) |
dosage | Strength, e.g. 1G, 50MG |
manufacturer | Manufacturer (fabricante) when published |
healthMinistryRegistration | The Brazilian health-ministry / ANVISA registration number (registro MS) |
prescriptionCategory, prescriptionStripeCode | The prescription stripe (tarja) classification and its code |
prescriptionRequired | Derived from the published stripe code |
controlledMedication | Controlled-substance flag |
psychotropicListCode | Psychotropic control-list code |
therapeuticClassCode, therapeuticClassName | Therapeutic class (ATC-style code plus its name) |
packageInsertUrl, packageInsertPage | The package insert (bula): the PDF and the store's own page |
weightKg | Shipping weight |
sellerName, benefitProgramAvailable | Marketplace seller name; whether a medicine-benefit programme applies |
breadcrumb | The product page's own category trail |
variants | One row per variant: sku, name, attributes, price, stockQuantity, inStock |
In incremental mode
changeType (NEW / UPDATED / REAPPEARED / UNCHANGED / EXPIRED), changedFields,
firstSeenAt, lastSeenAt.
Two modes
Search mode
Give keywords, catalogue sections, or both. Each keyword and each section is collected
separately, up to maxItems products and maxPages result pages each.
{"mode": "search","queries": ["dipirona"],"categories": ["medicamentos"],"maxItems": 50,"fetchDetails": true}
Keyword searches and section browsing read the store through different doors. Catalogue sections and pasted links are read from the store's pages; a keyword search is read from the store's own search interface (see Connection below for why). Both return the same product rows, filters and totals, and both are walked forward page by page in the same way.
URL mode
Paste any mix of product pages, catalogue section pages and search result pages. Each entry is
recognised by the page's own type, so you never have to say which is which. A link that already
names a page number (?p=3) is honoured, so you get results from page 3 onwards and not from
page 1.
{"mode": "url","urls": ["https://www.drogasil.com.br/dipirona-genericos-1g-com-10-comprimidos.html","https://www.drogasil.com.br/beleza/maquiagem/batom.html?p=2"],"fetchDetails": true}
Filters and sorting
Everything in the filter section applies in both modes: it narrows a keyword search, a browsed section, and a section or search link you pasted.
| Input | Applied by | Notes |
|---|---|---|
brands | the store | Spell the brand exactly as the store's own brand filter does |
minPrice / maxPrice | the store | In BRL |
soldBy | the store | Pharmacy's own stock, or marketplace partners |
excludeKits | the store | Drop bundled kits |
sortBy | the store | Relevance, price low to high, price high to low |
prescriptionFilter | this actor | The store publishes the prescription class but offers no filter for it |
inStockOnly | this actor | Live stock is only published on the product page, so this needs fetchDetails |
The two actor-applied filters are checked against the products that come back, so a run using them
may return fewer than maxItems.
If you paste a link that already carries its own filters, they are kept and the inputs above are added on top.
Recurring monitoring
Two separate features, both in the Resume & recurring updates section:
resumeFromRunIdcontinues ONE interrupted run. Paste the previous run or dataset ID and the products it already collected are skipped, and not billed again.incrementalModeis for a schedule. The actor remembers the previous run of the same search itself. The first run returns everything asNEW; later runs return onlyNEW,UPDATEDandREAPPEARED.emitUnchangedandemitExpiredare off by default because they return, and bill, extra rows.
State is kept separately per search, filter set and detail setting, so two different searches never
share a baseline. Set stateKey to name a campaign, or to deliberately share one.
scrapedAt is the only field excluded from change detection. Every price field, and live stock, are
included: a restock, a sell-out or a new multi-buy offer is a real change and is reported as
UPDATED with the field named in changedFields.
What you are charged for
- Product result for each product returned.
- Detail enrichment, charged once per product returned when
fetchDetailsis on. It is never charged for a product that incremental mode suppressed, and never for a product whose page could not be read. - Actor start, the platform's standard start event.
Turn fetchDetails off for a listing-only run: it is one read per result page instead of one read
per product, and the surcharge is not charged at all.
Send results into your apps (MCP connectors)
Optionally pipe results into the apps you already use, as well as into the dataset. Authorize a
connector under Apify, Settings, API & Integrations, then select it in mcpConnectors. Notion,
Linear, Airtable and Apify are offered in the picker, and any other Model Context Protocol server
you have authorized can be added by its URL.
For Notion, also set notionParentPageUrl and each product becomes a page under it. The other
connectors get a best-effort write, or a digest when the connector exposes no suitable write tool.
Each connector receives a condensed, human-readable summary per product: the product name plus the
key fields flattened to plain text, with nested objects collapsed to their main value and long lists
trimmed. The complete record always stays in the Apify dataset. maxNotifyListings caps how many
products are written per connector, defaults to 50, and never affects the dataset. Leaving
mcpConnectors empty skips this entirely, and a connector that fails never fails the run.
Notes on this store, measured live
Brazil only, and there is deliberately no country input. The store serves one market from one
catalogue: every page declares lang="pt-BR", every price is in BRL, there are no hreflang
alternates and no locale or country switcher anywhere in the site. A country input would be a knob
that changes nothing, so there is none. The sibling site drogaraia.com.br is a separate storefront
and is not in scope for this actor.
Reviews are not available. This is a real finding about the store, not an omission. The store
renders no review data on any server-rendered page: there is no rating, no review count and no
review body in the product payload, and no aggregateRating in its structured data. The product
page has an "Avaliações" (reviews) anchor, but the section behind it is filled in by a third-party
widget entirely in the browser, and that widget is switched off for the two product groups that
matter most here, medicines and over-the-counter medicines. Re-checked on 2026-08-28: the widget's
own endpoint for this store also answers every request with an empty body, so even a run that
rendered the page in a browser would have nothing to read. There is therefore no fetchReviews
input, because it could only ever return nothing.
Store pickup versus delivery is not published per product. The store decides fulfilment at
checkout from your postcode, so no product page states "available for pickup". What the store does
publish, and what this actor returns, is soldBy (its own stock, which its branches fulfil, versus
a marketplace partner that ships the order itself), requiresRefrigeration for cold-chain items,
and the controlled-medication flags, which are the constraints that actually change how an order can
be fulfilled.
Prices are national. The store renders one national price per product on its public pages; branch-level pricing is only resolved after a postcode is entered in a session, so this actor reports the public price.
Connection. The store turns away connections it does not recognise, so the run reads it through a connection built for exactly that kind of store, set up for you out of the box: you do not need to configure anything in the Connection section, and leaving Apify Proxy off entirely is likely to get the run refused. Any pool you select there is still honoured: it is tried on its own first, and it stays available as a fallback for the whole run. If the store declines a request the actor retries a bounded number of times and then reports the failure, rather than returning an empty result as if the search had simply found nothing.
Keyword search goes through the store's own search interface. Since 2026-09-04 the store's search page itself refuses automated readers on every connection (while catalogue sections, product pages and pasted links keep being served). A keyword search is therefore read from the same JSON interface the store's own website posts to when a shopper types a keyword; it returns the same products, filters, totals and page counts as the page did. Nothing changes in the input or the output.
A run that reads nothing at all tells you which of the three things went wrong, because each one needs a different next step from you:
| what the run reports | what happened | what to do |
|---|---|---|
| "Enable Apify Proxy in the Connection section" | no connection was set up, so nothing was ever sent | turn Apify Proxy on, or supply your own exits |
| "the connection selected for this run was refused before any request left it" | a connection was set up, but your account is not allowed to use the option that was picked, so the store never saw the request | pick another option in the Connection section, or one your plan includes |
| "Apify Proxy was already enabled for this run, so this is the store blocking this specific request" | the connection worked and the store itself turned the request away | retry later, or use a different route (browse by categories, or paste a link) |
The second and third cases used to be reported as the first one, which sent people off to enable a connection they already had.
Result counts. The store's own declared page ceiling is not the item count divided by the page
size: a 2,543 product section declares 42 pages at 48 rows a page, and 21 pages when the same
section is sorted by price. Both of the store's own signals are honoured, whichever ends the results
first, and an empty page ends them too. So maxPages is a ceiling, not a promise: a section can
finish earlier because the store says it has.
Local development
python3.12 -m venv .venv.venv/bin/pip install -r requirements.txt.venv/bin/python -m pytest tests -qapify run --purge
Verification
Re-verified against the live source on 2026-08-31 (build 1.1): the batom catalogue section reports 2,547 products server-side (2,543 at the previous audit, live churn); the Ruby Rose brand facet narrows it to 237 exactly as the site's own facet island declares, a 10 to 20 BRL price band narrows it to 245, the "sold by Drogasil" facet to 104, and dropping kits on the vitaminas section narrows 52,716 to 52,591. An unknown brand returns zero rows rather than silently ignoring the filter. The keyword route composes with the filters ("dipirona" reports 155 results; brand facets read off the search surface narrow it to 2 or 3 all-brand rows), and the price sorts reorder server-side (first row 6.22 BRL ascending vs 27.15 unsorted vs 4,182 descending). Pasted links resolve: a product page parses with its full regulatory block, and a section link carrying ?p=2 continues from page 2.