New to Kestra?
Use blueprints to kickstart your first workflows.
Orchestrate an Apify actor with Kestra and load the scraped dataset into Postgres on a schedule, with cost caps, an ingestion timestamp, and Slack alerts.
Turn an Apify web scrape into a clean, queryable Postgres table on a daily schedule. This blueprint runs an Apify Store actor, pulls its dataset, reshapes the raw JSON into typed columns, and bulk-loads the rows into Postgres as a fully declarative ELT pipeline. It solves the common problem of scraped data that lands as messy JSON nobody can query: here every run produces a consistent table with an ingestion timestamp, hard cost caps that stop a runaway crawl from becoming a runaway bill, and Slack notifications on both success and failure.
io.kestra.plugin.core.trigger.Schedule trigger fires every morning at 06:00 (cron 0 6 * * *).run_actor task runs an Apify actor with io.kestra.plugin.apify.actor.Run, defaulting to the Compass Google Maps Scraper. It enforces maxItems, maxTotalChargeUsd: 5, and memory: MB_2048 so pay-per-result cost stays bounded.get_dataset task fetches the actor's default dataset with io.kestra.plugin.apify.dataset.Get, and write_json persists it to Kestra internal storage as JSON.reshape task uses io.kestra.plugin.graalvm.python.FileTransform to map each raw record into typed, ordered fields (title, category, address, phone, website, total_score).to_csv task serializes the rows with io.kestra.plugin.serdes.csv.IonToCsv.create_table task runs io.kestra.plugin.jdbc.postgresql.Query to create public.apify_places if it does not exist, with an ingested_at TIMESTAMPTZ DEFAULT now().load_data task bulk-loads the CSV with io.kestra.plugin.jdbc.postgresql.CopyIn.notify_success task posts row count and reported cost to Slack, while an errors handler alerts the channel on any failure.maxItems and maxTotalChargeUsd.CopyIn instead of slow row-by-row inserts.Apify's own scheduler can run an actor, but it stops at the dataset. It cannot reshape the output, create a warehouse table, bulk-load Postgres, and notify Slack as one governed pipeline. Kestra wires these steps together declaratively in YAML, with event and schedule triggers, automatic retries, full execution lineage across the scrape, transform, and load, and a single errors block that catches failures anywhere in the flow. You get end-to-end orchestration that the scraping tool alone cannot provide.
APIFY_API_TOKENPOSTGRES_HOSTPOSTGRES_USERNAMEPOSTGRES_PASSWORDSLACK_WEBHOOK_URLactor_id, search_query, max_results) to validate the path.public.apify_places table in Postgres and the success message in Slack.actor_id input for any of the actors in the Apify Store and adjust the reshape script and table DDL to match its output.maxTotalChargeUsd and maxItems per use case.dbt or DuckDB transform step downstream for modeling.