Tutorial

How to Build a Job Search Agent with n8n (No Code)

Build an automated job search agent in n8n that finds new listings, filters by criteria, and sends daily email digests. Zero coding required.

Checking job boards daily is tedious. This tutorial builds an n8n workflow that searches for job listings automatically, filters them by your criteria (location, salary, remote status), and sends you a daily email digest. The entire workflow is no-code using n8n's visual builder. The search step uses the Scavio API via n8n's HTTP Request node at $0.005 per search. Running twice daily costs about $0.30/month.

Prerequisites

  • n8n installed (self-hosted or cloud)
  • A Scavio API key from scavio.dev
  • An email account for sending digests

Walkthrough

Step 1: Configure the n8n HTTP Request node for search

Set up the HTTP Request node to call the Scavio search API. This is the core search step of your workflow.

Python
# n8n HTTP Request Node Configuration:
# Method: POST
# URL: https://api.scavio.dev/api/v1/search
# Authentication: None (we use header auth)
# Headers:
#   x-api-key: {{$env.SCAVIO_API_KEY}}
#   Content-Type: application/json
# Body (JSON):
#   {
#     "query": "software engineer remote jobs 2026",
#     "country_code": "us",
#     "num_results": 10
#   }

# Python equivalent for testing outside n8n:
import requests, os

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']

def search_jobs(query: str) -> list:
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
        json={'query': query, 'country_code': 'us', 'num_results': 10})
    return resp.json().get('organic_results', [])

results = search_jobs('software engineer remote jobs 2026')
for r in results[:3]:
    print(f'{r["title"][:50]}: {r["link"]}')

Step 2: Add job filtering logic

Filter search results to match your criteria. In n8n, use an IF node or Function node to apply these filters.

Python
# n8n Function Node - Filter Jobs
# This code runs inside n8n's Function node

# For Python testing:
def filter_jobs(results: list, criteria: dict) -> list:
    filtered = []
    for r in results:
        text = (r.get('title', '') + ' ' + r.get('snippet', '')).lower()
        # Check required keywords
        has_required = all(kw.lower() in text for kw in criteria.get('required_keywords', []))
        # Check excluded keywords
        has_excluded = any(kw.lower() in text for kw in criteria.get('excluded_keywords', []))
        # Check salary mentions
        has_salary = any(s in text for s in ['$', 'salary', 'compensation', '/yr', '/year'])
        if has_required and not has_excluded:
            filtered.append({
                'title': r['title'],
                'url': r['link'],
                'snippet': r.get('snippet', ''),
                'has_salary_info': has_salary
            })
    return filtered

criteria = {
    'required_keywords': ['remote', 'engineer'],
    'excluded_keywords': ['senior staff', 'principal', 'intern'],
}

filtered = filter_jobs(results, criteria)
print(f'{len(filtered)}/{len(results)} jobs match criteria')
for j in filtered:
    print(f'  {j["title"][:50]}')

Step 3: Build the email digest

Format filtered jobs into an HTML email digest. In n8n, use the Send Email node with the formatted body.

Python
from datetime import datetime

def build_digest(jobs: list, query: str) -> str:
    date = datetime.now().strftime('%B %d, %Y')
    html = f'<h2>Job Search Digest - {date}</h2>\n'
    html += f'<p>Search: <em>{query}</em> | Found: {len(jobs)} matches</p>\n'
    html += '<hr>\n'
    for i, job in enumerate(jobs, 1):
        html += f'<h3>{i}. <a href="{job["url"]}">{job["title"]}</a></h3>\n'
        html += f'<p>{job["snippet"][:200]}</p>\n'
        if job.get('has_salary_info'):
            html += '<p><strong>Has salary information</strong></p>\n'
        html += '<hr>\n'
    html += f'<p><small>Cost: $0.005 | Powered by Scavio Search API</small></p>'
    return html

# n8n Cron Trigger: Run at 8am and 6pm daily
# n8n Schedule: 0 8,18 * * *

digest = build_digest(filtered, 'software engineer remote jobs 2026')
print(f'Digest generated: {len(digest)} chars')
print(f'Daily cost: 2 searches = $0.01')
print(f'Monthly cost: ~$0.30')

Python Example

Python
import requests, os
from datetime import datetime

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']

def job_search_digest(query, required=None, excluded=None):
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
        json={'query': query, 'country_code': 'us', 'num_results': 10})
    jobs = []
    for r in resp.json().get('organic_results', []):
        text = (r['title'] + ' ' + r.get('snippet', '')).lower()
        if required and not all(k.lower() in text for k in required):
            continue
        if excluded and any(k.lower() in text for k in excluded):
            continue
        jobs.append({'title': r['title'], 'url': r['link']})
    print(f'Job Digest - {datetime.now().strftime("%B %d")}:')
    for j in jobs:
        print(f'  {j["title"][:50]}: {j["url"]}')
    return jobs

job_search_digest('remote python developer jobs 2026', required=['remote', 'python'])

JavaScript Example

JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;

async function jobDigest(query, required = [], excluded = []) {
  const resp = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST',
    headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ query, country_code: 'us', num_results: 10 })
  });
  const results = (await resp.json()).organic_results || [];
  const jobs = results.filter(r => {
    const text = (r.title + ' ' + (r.snippet || '')).toLowerCase();
    return required.every(k => text.includes(k.toLowerCase()))
      && !excluded.some(k => text.includes(k.toLowerCase()));
  });
  jobs.forEach(j => console.log(`${j.title.slice(0, 50)}: ${j.link}`));
  return jobs;
}

jobDigest('remote python developer jobs 2026', ['remote', 'python']);

Expected Output

JSON
software engineer remote jobs 2026: https://...
Remote Software Engineer - TechCorp: https://...
Senior Remote Engineer at StartupX: https://...

5/10 jobs match criteria
  Remote Software Engineer - TechCorp
  Full Stack Engineer - Remote at ScaleUp

Digest generated: 1240 chars
Daily cost: 2 searches = $0.01
Monthly cost: ~$0.30

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

n8n installed (self-hosted or cloud). A Scavio API key from scavio.dev. An email account for sending digests. A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Build an automated job search agent in n8n that finds new listings, filters by criteria, and sends daily email digests. Zero coding required.