Two saved job descriptions connect through matching source passages.
Compare the same listing at two known times.

A term is one decision phrase you choose to check. Examples are appointment fraction, employment type, pay wording, and work location. Appointment fraction means the share of a full job, such as the listing words "100%" or "50%".

Do these eight steps

  1. Choose the terms that can change your decision.

Read the original listing words for those terms. A title, an optional seniority label, or the search words are not the full requirement. Seniority can be missing. If the chosen phrase is unclear, keep it unclear. Do not guess a value. These steps cover the public-term comparison only. They do not explain candidate status, reference checks, or hiring intent.

  1. Start with your old save, then collect a new row.

The old body must already be in your files. The Indeed Jobs Scraper is an Actor. An Actor is a hosted data collection program. It collects current public rows. It cannot rebuild an old description. It does not give employer edit times, applicant status, or automatic term labels. You do the comparison stated here.

A date written inside the job text is not an edit time. For each save, keep the run identity, the source identity, the input, scrapedAt, descriptionStatus, and the raw text. scrapedAt is the time that row was collected. A run is one execution of the Actor.

  1. Match the same listing before you compare words.

Match the same source namespace and the same jobId first. A namespace is the site that owns the ID. Then check jobUrl, the role, and the company. Keep jobId as text. If a sheet stores it as a number, long digits can change. The same title alone cannot prove that two rows are one version.

A different source ID stays unresolved. An uncertain repost also stays unresolved. Use the published duplicate and repost guide for that match. Until the relation is settled, do not compare the texts. Keep the identity conflict in your notes.

  1. Require comparable text for the chosen term.

Read descriptionStatus before you look for a word difference. full means the source text was available and was saved in descriptionText. missing means that text was not available. This Actor has no snippet status. full does not promise the employer's whole document.

Missing old text against full new text is newly available evidence. It is not proof that the employer changed a requirement. A short excerpt against a full body can create a false difference. The extra words may have existed when you did not hold them. Save the availability state first. Only then compare passages.

  1. Keep the raw text, and make a comparison copy.

Leave the raw descriptionText unchanged. Make a second copy only for spacing. In that copy, join declared whitespace when the meaning stays the same. Whitespace means spaces, tabs, and line breaks. You may treat markup that only makes those same breaks as the same spacing. Do not remove percentages, currency words, units, negation, or other qualifiers. The word "not" can reverse a rule. A percent value can change the decision.

Save the exact old passage and the exact new passage. Save their positions in the source text when you know them. If a position is unknown, write unknown. Do not write zero.

  1. Classify one state for the chosen term.

Use one of these five states:

  • no_observed_change
  • formatting_only
  • substantive_wording_change
  • newly_available_text
  • unresolved

Use substantive_wording_change when the same listing has full comparable text and the chosen words differ in meaning. Use formatting_only when only the declared spacing differs. Use no_observed_change when that chosen term is the same. That state does not cover fields you did not read. Use newly_available_text when the old source text was not available and later becomes available. A missing term is not missing text. Old full comparable text without the chosen term, and new full text that adds the term, can be a substantive_wording_change. Use unresolved when identity is not settled.

A text difference points to a review. It does not by itself prove a new employment condition. Read the current official employer page before you act on appointment or pay wording.

  1. Report the time limit in plain words.

Write that the change was observed between the old scrapedAt and the new scrapedAt. Do not write that the employer edited the listing at the new scrapedAt. Other source processing can also change the words you see. You cannot tell how many edits fell between the two saves. That count is unknown. Unknown is not zero, and it is not one. The current run does not provide automatic history.

A listing you notice for the first time is a different job. Use the published new-alert guide for that. A count of listings is also a different job. Use the published listing-trend guide for counts.

  1. Deliver one paired record.

Include the identity, the raw passages, the availability, the comparison rule, the state, both times, and the current source check. The current source check is what the official employer page says when you read it, or a note that you have not read it yet. If a material term is still unclear, ask the employer contact through your own process. These steps do not send messages. They do not read private application status.

Save these fields

Use these row fields from the Actor. Optional fields can be absent. Absent means the value was not supplied. It does not mean zero, and it does not mean the employer has none.

Save these fields
FieldWhat it is
jobIdSource identity. Keep it as text.
titleRole name. It is not full identity.
companyNameEmployer name, for the identity check.
locationRawPlace text as the source showed it.
descriptionTextListing words saved for that row.
descriptionStatusfull or missing, for available source text.
jobUrlListing address, for the identity check.
querySearch words used for that row.
searchLocationPlace used in the search.
scrapedAtTime the Actor saved the row.

seniority, employmentType, salaryRaw, postedAt, and postedAtRaw are optional. Any of them can be missing. postedAt, when present, is a posted time from the source. It is not an employer edit time. A date inside descriptionText is not an edit time either.

Save the raw rows, the input that ran, and the run output. Also save proof of the row cap or of a failed run. A cap is the maxItems stop. A successful empty run does not prove that no jobs exist. A capped run does not prove that you collected every listing.

Set a small first run

A Task is a saved input preset. The current public Task is a starting input. It is not proof that the comparison runs by itself. Public build 1.2.14 was checked at 2026-10-13T05:55:51.545104+00:00. It accepts searchTerm, country, location, maxItems, maxPagesPerSearch, postedWithinDays, sortBy, and saveOnlyUniqueItems.

The saved Task input is:

json
{
  "country": "us",
  "searchTerm": "software engineer",
  "maxItems": 100,
  "postedWithinDays": "7",
  "sortBy": "date",
  "maxPagesPerSearch": 2,
  "saveOnlyUniqueItems": true
}
Set a small first run

For a first check, set one intended role and one market. Set country and searchTerm for that pair. Add location only when you need one place. Replace the broad row cap with maxItems 2 and maxPagesPerSearch 1. postedWithinDays and sortBy only limit which current listings the run asks for. They do not return last week's wording. saveOnlyUniqueItems can keep one current row for an item. It does not rebuild older wording. You still need your own older save.

A compatible check of this build returned two source IDs and URLs. Both rows had full descriptionText. The run hit its cap. That check shows that text collection is supported. It is not a live finding for the examples below. It does not mean that only two jobs exist.

Work the five fictional pairs

The five pairs below are original fiction. They teach the states. They are not Actor results, and they are not employer findings. No year is given for these fiction times. Do not treat them as the build check time.

Work the five fictional pairs
PairAvailabilityIdentityDifferenceStateNext check
J1full both timesSame source ID and roleAppointment words differsubstantive_wording_changeReview the passages. Then read the current official employer page.
J2full both timesSame listingLine breaks onlyformatting_onlyDo not treat spacing as a new term.
J3missing, then fullSame listingText becomes availablenewly_available_textKeep the new text. Do not claim a changed term.
J4Not usedDifferent source ID, same titleIdentity is unsettledunresolvedStop. Use the duplicate and repost guide.
J5full both timesSame listingChosen term matchesno_observed_changeReport that term only. Check other terms apart.

J1 has full text at October 1 10:00 UTC: "Full-time appointment, 100%." The same source ID and role has full text at October 8 10:00 UTC: "Career appointment, 50%." Both saves are full, so this is not newly available text. The spacing rule cannot explain the change. "Full-time" and "Career" are different appointment words. "100%" and "50%" are different fractions. The state is substantive_wording_change. The two times are seven days apart. Report a change observed between October 1 10:00 UTC and October 8 10:00 UTC. Do not call October 8 the employer edit time. Do not explain why the words changed. The edit count between the saves is unknown.

A paired record for J1 can look like this:

text
identity: same fictional source jobId both times; role matches; company and jobUrl are not supplied
old scrapedAt: October 1 10:00 UTC
new scrapedAt: October 8 10:00 UTC
descriptionStatus: full / full
old passage: Full-time appointment, 100%.
new passage: Career appointment, 50%.
positions: unknown
comparison rule: raw text kept; spacing rule does not remove percentages or appointment words
state: substantive_wording_change
time reading: change observed between the two scrapedAt values
current source check: not done in the fiction
Work the five fictional pairs

You might read the current official employer page for J1 and see 50% at the new observation time. That reading still cannot explain private hiring choices. It cannot prove that your earlier reading of the appointment was right. You need the saved old source text for that proof.

J2 is full at both times. The only difference is line breaks under the declared whitespace rule. The fiction texts are:

text
old: "Same words stay."
new: "Same words\nstay."
Work the five fictional pairs

The comparison copy joins the line break. Both copies then read "Same words stay." The meaning is unchanged. The state is formatting_only. Do not report a new employment condition from those breaks.

J3 has a missing description on the old row and a full description on the new row. The old chosen term was not observed. The state is newly_available_text. You may keep the new passage as new evidence. You may not say the employer changed the term. A word difference was not computed, because the old words were absent.

J4 has a different source ID and the same title. Same title is not same identity. Do not compare the bodies as two versions of one job. The state is unresolved until the duplicate and repost guide establishes the relation. If that guide does not settle the pair, leave it unresolved.

J5 has full text at both times, and the chosen term has the same words. The state is no_observed_change for that term. This is not proof that every field stayed the same. Another term can still differ. Check each chosen term on its own.

The five pairs give one substantive wording change, one formatting change, one availability change, one unresolved identity, and one unchanged term. That is five states, with one pair each. None of these counts is a market count.

Sources & further reading

By Chronometrica · Updated

Back to top ↑