View a County Property Tax Lookup Form

Site county-taxes.netTask view-property-tax-lookup-formVersion v5Updated Aug 17, 2026Category government

Navigate directly to a county-taxes.net property-tax lookup page, handle its Cloudflare challenge, use address or parcel autocomplete when present, inspect or submit the rendered lookup form, and optionally open the returned tax-bill details. This skill was captured from a live agent session on county-taxes.net and publishes here verbatim, exactly as an agent receives it.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Purpose

Open a county-taxes.net property-tax lookup form, confirm that the usable fields have rendered after any anti-bot challenge, perform an address or parcel lookup including autocomplete selection when required, and optionally inspect the returned tax-bill details.

When to Use

Use when the caller needs to inspect, document, or use a county-taxes.net property-tax lookup form or view the details returned for a parcel, especially when the page is protected by Cloudflare Turnstile or requires selecting an autocomplete suggestion before displaying the property record.

Workflow

  1. Construct the direct page URL using https://county-taxes.net/{county-slug}/property-tax and navigate with page-load waiting. For San Francisco, use https://county-taxes.net/ca-sanfrancisco/property-tax.
  2. Allow the page to settle after navigation. If a Cloudflare challenge is present, invoke the browser's Cloudflare solver. Wait for the challenge and page content to settle; if it remains, invoke the solver in wait mode and, only if necessary, click challenge controls matching input[type='checkbox'], .cf-turnstile, #cf-turnstile, [id*='turnstile'], iframe, then wait again.
  3. Confirm that the lookup form controls are visible rather than treating a challenge page as the form. Run this self-contained evaluator on the loaded page:
(() => {
const visible = el => {
const s = getComputedStyle(el), r = el.getBoundingClientRect();
return s.display !== 'none' && s.visibility !== 'hidden' && r.width > 0 && r.height > 0;
};
const text = el => (el?.textContent || '').replace(/\\s+/g, ' ').trim();
return [...document.querySelectorAll('form')].map((form, formIndex) => ({
formIndex,
action: form.action || location.href,
method: (form.method || 'get').toLowerCase(),
fields: [...form.querySelectorAll('input, select, textarea, button')]
  .filter(visible)
  .map((el, index) => {
    const id = el.id;
    const label = id ? document.querySelector(`label[for="${CSS.escape(id)}"]`) : el.closest('label');
    return {
      index,
      tag: el.tagName.toLowerCase(),
      type: el.getAttribute('type') || null,
      name: el.getAttribute('name') || null,
      id: id || null,
      role: el.getAttribute('role') || null,
      ariaLabel: el.getAttribute('aria-label') || null,
      placeholder: el.getAttribute('placeholder') || null,
      label: text(label),
      options: el.tagName === 'SELECT' ? [...el.options].map(o => ({value:o.value, text:text(o)})) : undefined
    };
  })
}));
})()
  1. For a lookup, fill the visible search control matching input[placeholder*='block-lot'], input[placeholder*='Bill'], input[type='search'], input[role='combobox'] with {property-or-parcel-query}. Wait for the suggestions to populate. This site may require choosing the suggestion rather than submitting the raw text. Inspect and select the first visible a[role='option'] whose normalized text matches or contains {property-or-parcel-query}; if several match, choose the most specific address/parcel suggestion. A visibility-aware autocomplete extractor and selector is:
(() => {
const visible = el => { const s=getComputedStyle(el), r=el.getBoundingClientRect(); return s.display!=='none' && s.visibility!=='hidden' && r.width>0 && r.height>0; };
const clean = el => (el?.textContent || '').replace(/\\s+/g,' ').trim();
const options = [...document.querySelectorAll('a[role="option"], [role="option"]')].filter(visible).map((el,index)=>({index,tag:el.tagName.toLowerCase(),text:clean(el),href:el.href||null,selected:el.getAttribute('aria-selected')||null}));
const query = [...document.querySelectorAll('input[placeholder*="block-lot"], input[placeholder*="Bill"], input[type="search"], input[role="combobox"]')].find(visible)?.value || '';
const normalized = query.toLowerCase().trim();
const match = options.find(o => normalized && o.text.toLowerCase().includes(normalized)) || options[0];
if (match) {
  const el = [...document.querySelectorAll('a[role="option"], [role="option"]')].filter(visible)[match.index];
  el?.click();
}
return {query, options, selected: match || null};
})()
  1. Wait for the lookup response and any details panel to finish rendering. If no autocomplete option appears, submit by clicking the first visible control matching [aria-label*=search i], button[type=submit], form button; if none exists, dispatch a bubbling Enter key event on the active input.
  2. If the caller requests the tax-bill details and the returned state exposes a visible link or button whose trimmed text is exactly View, click it and wait for the details view to load. Do not guess a result URL because no stable post-lookup URL was observed. A runnable visibility-aware click helper is:
(() => {
const visible = el => { const s=getComputedStyle(el), r=el.getBoundingClientRect(); return s.display!=='none' && s.visibility!=='hidden' && r.width>0 && r.height>0; };
const view = [...document.querySelectorAll('a, button')].find(el => visible(el) && /^view$/i.test((el.textContent||'').replace(/\\s+/g,' ').trim()));
if (!view) return {clicked:false};
view.click();
return {clicked:true,text:(view.textContent||'').replace(/\\s+/g,' ').trim()};
})()
  1. Extract the currently rendered lookup/details state in one page evaluation:
(() => {
const visible = el => { const s=getComputedStyle(el), r=el.getBoundingClientRect(); return s.display!=='none' && s.visibility!=='hidden' && r.width>0 && r.height>0; };
const clean = v => (v||'').replace(/\\s+/g,' ').trim();
const options = [...document.querySelectorAll('a[role="option"], [role="option"]')].filter(visible).map(el=>({text:clean(el.textContent),href:el.href||null,selected:el.getAttribute('aria-selected')||null}));
const fields = [...document.querySelectorAll('input, select, textarea')].filter(visible).map(el=>({name:el.name||null,id:el.id||null,value:el.value||'',placeholder:el.getAttribute('placeholder')||null}));
const rows = [...document.querySelectorAll('table tr, dl, .detail, [class*="detail"], [class*="tax"]')].filter(visible).map(el=>({text:clean(el.textContent),cells:[...el.querySelectorAll(':scope > th, :scope > td, :scope > dt, :scope > dd')].map(x=>clean(x.textContent)).filter(Boolean)})).filter(x=>x.text);
return {url:location.href,title:clean(document.title),fields,autocompleteOptions:options,details:rows};
})()
  1. Capture any requested screenshot only after the form is rendered, after the autocomplete result loads, or after the tax-bill details finish loading. Batch navigation, challenge handling, input, suggestion selection, optional View, extraction, and screenshot capture where the browser interface permits.

Site-Specific Gotchas

  • The direct property-tax route is /ca-sanfrancisco/property-tax for San Francisco; county slugs use the {state}{county} pattern shown by this route.
  • The site may remain behind Cloudflare after initial navigation. Allow the solver to complete before inspecting or submitting; the challenge can require an additional wait-mode solve and interaction with a Turnstile checkbox or iframe.
  • Do not treat a challenge page as the lookup form. Confirm that property-tax form controls are visible before capturing the screenshot or running the evaluator.
  • The lookup input is exposed by a placeholder containing block-lot or Bill, or as a search input/combobox. Submission may require an explicit search/submit button, but the observed San Francisco flow requires waiting for and clicking an autocomplete option matching the entered parcel or address.
  • Returned lookup results may require an explicit View link or button before the tax-bill details are displayed. Match the visible control by text rather than assuming a result URL or opaque identifier.
  • No stable result-page URL or result-row structure was observed; the selected autocomplete result can leave the browser on the same property-tax route. Do not guess a direct post-lookup URL. Use the current-page evaluator after the response settles.
  • Raw detail selectors such as [class*="detail"] and [class*="tax"] are fallback selectors and may include container text; prefer the returned cells or confirmed labels when presenting structured tax fields.

Expected Output

A screenshot showing the rendered county property-tax lookup form, the autocomplete result state, or the returned tax-bill details, depending on the request. Include the form evaluator's array of forms and visible controls when form inspection is requested, the submitted query and selected autocomplete option when a lookup is performed, and the current URL plus extracted visible detail rows after the response finishes loading. Extract result details only from selectors confirmed on the returned page.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=county-taxes.net&task=view-property-tax-lookup-form