LocalHarvest Farms and Farmers Markets Scraper
Pricing
from $2.40 / 1,000 item processeds
LocalHarvest Farms and Farmers Markets Scraper
Search LocalHarvest farms, farmers markets, CSAs and local-food listings. Export public locations, products, seasons, contacts and profile URLs for directory refreshes.
Pricing
from $2.40 / 1,000 item processeds
Rating
0.0
(0)
Developer
Automation Lab
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Refresh local-food directories with structured public LocalHarvest farms and farmers markets profiles. Search by location, listing category, and optional text, or export a supplied list of profile URLs. Each row includes business identity, location, public contact links, description, crops, seasons, and the original profile URL when available.
Who is this for?
Food buyers can build a shortlist of nearby producers. Local directory editors can refresh listing details. Researchers can compare farm, CSA, farmers-market, and co-op coverage across locations. The Actor collects a snapshot, not a historical archive or a change-alert service.
Why use this Actor?
- Export full profiles rather than only short search snippets.
- Use stable LocalHarvest IDs to join recurring snapshots.
- Collect all displayed seasonal crop tabs without browser interaction.
- Deduplicate repeated profile URLs within a run.
- Keep source links alongside business information for verification.
Getting started
- Enter a city and state, such as
Portland, OR, or a US ZIP code. - Choose a listing type, or keep
all. - Set a small
maxItemsfor your first run. - Run the Actor and inspect the default dataset.
- Download JSON, CSV, or Excel using Apify's dataset export controls.
Example search:
{"location":"Portland, OR","listingType":"farms","maxItems":20,"maxPages":10}
Direct profile example:
{"profileUrls":["https://www.localharvest.org/house-in-the-woods-csa-M171"],"maxItems":1}
Direct profile URLs cannot be combined with search filters. This is validated, not silently ignored.
Input parameters
| Parameter | Meaning |
|---|---|
location | City/state or ZIP passed to LocalHarvest's proximity search; not a strict city boundary. |
searchTerm | Optional native search text; maximum 120 characters. Matching and ranking are controlled by LocalHarvest, not an exact-phrase contract. |
listingType | all, farms, markets, csa, groceries, or other. Default all. |
profileUrls | Up to 1,000 public profile URLs ending in -M and a numeric ID. No subpages, fragments, or query strings. |
maxItems | Global unique output-profile limit, default 20, range 1–10,000. Zero/unlimited are not supported. |
maxPages | Search-result page ceiling, default 10, range 1–1,000. Ignored for direct profiles. |
Provide location and/or searchTerm for discovery, or profileUrls for direct export. Search may finish before maxItems when the source is exhausted, maxPages is reached, or the run times out. Limit ceilings do not promise exhaustive national coverage.
Extracted data
| Field | Contents |
|---|---|
listingId, name, profileUrl | Stable source listing ID, displayed name, canonical profile URL. |
listingType, location | Displayed profile category and human-readable location. |
streetAddress, city, state, postalCode, country | Public address components when exposed in source structured data. |
description | Full profile description, with whitespace normalized. |
phone, email, website | Public business contact fields when available. Email is only collected from an exposed mailto link, never inferred. |
contactUrl | LocalHarvest's public contact-form URL, not an email address. No form is submitted. |
products, seasons | Unique product labels across displayed seasonal tabs, plus season labels. |
csaSeason, marketChannels | Displayed CSA operating season and selling channels. |
lastUpdated, scrapedAt | Source update label and UTC collection timestamp. |
Unavailable scalar fields are null; absent list fields are empty arrays. The profile category may differ from the selected search category: a CSA search can return a Family Farm offering shares. Co-ops are included when LocalHarvest classifies them as groceries.
Output example
A shortened example from a public farm profile; the full dataset also contains the remaining address and contact fields:
{"listingId": "20287","name": "Hood River Organic","profileUrl": "https://www.localharvest.org/hood-river-organic-M20287","listingType": "Family Farm","location": "Hood River, Oregon","city": "Hood River","state": "OR","csaSeason": "Year round","marketChannels": ["Online Store", "CSA", "Wholesale"],"seasons": ["Winter", "Spring", "Summer", "Fall"]}
How much does it cost to export LocalHarvest profiles?
Pay-per-event pricing charges a one-time $0.005 start fee and one item event for each profile saved. At the BRONZE tier, the item price is $0.004004 per profile. Other plan tiers are shown in the Pricing tab.
Example BRONZE run totals, including the start fee:
| Exported records | Estimated run total |
|---|---|
| 1 | $0.009004 |
| 10 | $0.04504 |
| 100 | $0.4054 |
An empty search has only the start fee. Invalid input is rejected before the start charge. There is no separate event charge for products, seasonal labels, or contact fields within a profile.
Search scope and pagination
The Actor follows the source's next-page links, up to maxPages or maxItems. With only a location and listingType all, LocalHarvest serves a mixed-category overview (currently about eight cards) without pagination. Choose a specific type for deeper paginated results; all does not mean an exhaustive combined directory. Source ordering can prioritize supporters or listings outside the named city. Do not treat the first result as the closest business or infer a geographic radius. Text search semantics are source-defined. No client-side exact-name or product filter is applied.
The products array unions all displayed seasonal tabs; it does not preserve a product-to-season mapping or verify current stock. Source update dates can be old or self-reported. Confirm opening hours, share availability, and contact details before acting on them.
Reliability and limitations
Search and profile requests use an included US residential proxy with bounded fresh-session recovery. The company pays the proxy cost; you do not supply an account, paid data API, or cookies. Detail concurrency is limited to three and transient failures have at most three attempts, each with a hard timeout.
Unrecognized pages, blocked responses, missing profiles, and exhausted network retries fail the run honestly. Rows saved before a failure remain partial results, not a successful complete export. Malformed URLs and unsupported filter combinations fail early. Duplicate input URLs are exported once, and maxItems is a global run limit.
Integrations
Schedule recurring snapshots in Apify and compare rows downstream by listingId. Send new dataset rows to Google Sheets, Make, n8n, or a database to maintain a local-food directory. Use a dataset webhook to start your own comparison workflow after successful completion. Scheduling and integrations are platform features; the Actor itself does not send alerts or maintain history.
API access
Start one run with your own Apify API token:
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~localharvest-farms-markets-directory/runs' \-H "Authorization: Bearer $APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"location":"Portland, OR","listingType":"farms","maxItems":20}'
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/localharvest-farms-markets-directory').call({location: 'Portland, OR', maxItems: 20});const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 20 });console.log(items);
Python:
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/localharvest-farms-markets-directory').call(run_input={'location': 'Portland, OR', 'maxItems': 20})rows = client.dataset(run['defaultDatasetId']).list_items(limit=20).itemsprint(rows)
MCP access
Select this stable Actor subset in Claude Code:
claude mcp add --transport http apify \'https://mcp.apify.com?tools=automation-lab/localharvest-farms-markets-directory'
For Claude Desktop, Cursor, and VS Code clients that support remote HTTP MCP:
{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/localharvest-farms-markets-directory"}}}
Authenticate using your client's supported Apify flow. Discover actual tool names and arguments through scoped tools/list; selecting an Actor also exposes run/data helper tools, not exactly one tool.
Example prompt: “Find up to 20 LocalHarvest farm profiles near Portland, Oregon, and show names, locations, and profile links.” Only start a run when authorized. Retain the returned run ID and storage IDs; they are metadata, not result rows. If still running after the server wait (at most 45 seconds), check the same run with bounded backoff, for example 2, 4, then 8 seconds capped at 10, with a total 120-second deadline. Configure the client timeout above the selected server wait plus transport margin. On timeout recover that known run, never restart just to poll. At the deadline report pending with its ID.
After success, fetch bounded dataset pages with explicit limit, offset, and needed fields. A useful consumer budget is 20 source rows per page, at most 100 rows and 64 KiB of serialized UTF-8 output admitted to model context, whichever comes first. Enforce the byte budget host-side, including oversized rows; disclose omissions and the continuation offset. If your client cannot intercept oversized responses, do not claim a hard byte guarantee. Failed-run rows are partial. Keep full exports outside model context. No universal token-saving guarantee is made.
Legality and privacy
Collect only public information for legitimate research and directory maintenance. Public contact details can still be personal data: comply with applicable privacy laws, source terms, retention policies, and outreach rules. This Actor does not grant marketing consent or access private accounts, reveal hidden emails, submit contact forms, or crawl external business sites.
No AI model is used during extraction or to generate dataset content. Run datasets and logs remain in your Apify account under your storage retention settings until expired or deleted; delete them through Apify when no longer needed. No cross-run cache is maintained. Proxy credentials are protected runtime configuration, never public input. Apify hosts execution/storage and supplies proxy routing; our private diagnostic service receives only sanitized failure reports. This Actor is independently developed and is not affiliated with or endorsed by LocalHarvest. For support, open an issue from the Actor's Apify page.
Failed operations send sanitized diagnostic input, exceptions, and Actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed, and reports are retained for 30 days.
FAQ and troubleshooting
Why are some contacts missing? LocalHarvest may expose only a contact form. Its link is returned as contactUrl; no email is guessed.
Why did I receive fewer profiles than maxItems? The source may have fewer matches, or maxPages stopped pagination. A failed or timed-out run can leave partial rows. Check its status and logs.
Why are listings outside my city? Native search uses proximity and source ranking, not an exact municipal boundary.
Can I run this every week? Yes, schedule snapshots through Apify and compare them in your own workflow. No historical database or built-in change notifications are included.
Can I search all listing types? Choose all, or the supported native categories. Groceries includes food co-ops; other covers the source's miscellaneous local-food businesses. Product, shop, photo, and event entities are not exported as separate records.
Related workflows
This is a standalone LocalHarvest directory product. Use Apify dataset exports and integrations for spreadsheet and directory refreshes. It does not replace a product-price feed, lead-consent system, or inventory API.