Skip to content

is_remote silently ignored when hours_old is set (Indeed) — surface a warning instead #353

Description

@RodionKonstantinov

Summary

When both is_remote=True and hours_old=N are passed to scrape_jobs() for the Indeed scraper, is_remote is silently dropped from the API filter, and onsite jobs come back in the result set. This is documented as a mutual-exclusion limitation, but the silent fallback makes it easy to miss in production code.

Repro

from jobspy import scrape_jobs

df = scrape_jobs(
    site_name=["indeed"],
    search_term="Data Engineer",
    location="United States",
    is_remote=True,
    hours_old=24,
    country_indeed="usa",
    results_wanted=10,
    verbose=0,
)
print(df[["title", "location", "is_remote"]])

Expected

Either:
- Only remote jobs returned (i.e., the is_remote filter is honoured, perhaps by issuing a second query or by client-side filtering), or
- A logging. warning (or UserWarning) telling the caller that is_remote is being dropped because hours_old was set.

Actual

9 of the 10 returned rows have is_remote=False (varying onsite locations across the US). No warning, no log linethe parameter is simply skipped because of the if/elif chain in jobspy/indeed/__init__.py::_build_filters:

if self.scraper_input.hours_old:
    filters_str = ...   # date filter wins
elif self.scraper_input.easy_apply:
    ...
elif self.scraper_input.job_type or self.scraper_input.is_remote:
    ...   # never reached when hours_old is set

The README does mention "Only one from this list can be used in a search: hours_old / job_type & is_remote / easy_apply" under the Indeed section, but downstream code that builds these arguments dynamically (search-pass loops, configurable time windows) won't get any
Feedback that the filter is being silently ignored.

Impact

In our agent, this means LLM/eval cycles burn on jobs we'd reject on location anyway. We worked around it by post-fetch filtering on the returned is_remote column, but we only spotted it after the match rate had halved and we manually inspected the data.

Suggested fix

A 3-line change at the top of _build_filters (or in scrape_jobs itself) to log a warning when conflicting filters are passed:

if self.scraper_input.hours_old and self.scraper_input.is_remote:
    logger.warning(
        "Indeed: is_remote is ignored when hours_old is set "
        "(see README — only one of hours_old / is_remote+job_type / easy_apply "
        "can be used per search). Pass hours_old=None and filter on is_remote, "
        "or filter results client-side."
    )

Same idea for easy_apply + job_type/is_remote.

Even betteraccept both and run a second query (or post-filter the DataFrame on is_remote) so callers get the result they asked for. But the warning alone would have saved us a few hours of debugging.

Environment

- python-jobspy==1.1.82 (PyPI, latest)
- Python 3.14
- Windows 11

Thanks for the libraryit works well overall, this is the only sharp edge we've hit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions