Use item[last()] to select the last matching item child in the current XPath context. To select the last item in a complete document-wide result, group the path first: (//item)[last()]. Those expressions are not interchangeable: //item[last()] can return one last item child for every matching parent.
The expression you need
XPath evaluates a predicate against a context list. The last() function returns the size of that list, and positions are one-based. Therefore, item[last()] keeps the item whose position equals the list size—the final matching child of the current context node.
item[last()]
The same relationship can be written explicitly as item[position() = last()]. The shorter form is normally clearer.
Scope determines what “last” means
Before writing the predicate, describe the set you want in ordinary language. Are you asking for the last child under each parent, the last descendant under one node, or the last node in the entire document result? Attach [last()] to the step or grouped path that represents that set.
#1 Best Overall
Last child of the current context node
para[last()]
This selects the last para child of the node supplied as the context. It does not search arbitrary descendants.
Last matching child under each parent
//item[last()]
The abbreviated // path expands through descendant-or-self steps. The predicate is applied to the item child step reached for each parent, so the result can contain several nodes: one last item child for every parent that has matching children.
For example, if three sections each contain several item elements, this expression may return three nodes rather than one. That is correct XPath behavior, not a failure to find the document’s final item.
Last item in the whole document result
(//item)[last()]
Parentheses force XPath to evaluate all matching item nodes first. The outer predicate then keeps the final node in that complete result.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Last descendant beneath the current node
(.//item)[last()]
The leading dot makes the scope explicit: begin at the supplied context node, search its descendants, then select the last item in that scoped result. This is usually safer than relying on an implicit document context in reusable automation code.
Rank #2
- Used Book in Good Condition
Common expressions compared
| Goal | XPath | Possible result |
|---|---|---|
| Last matching child of the current node | item[last()] |
One node, if the context has matching children |
| Last item child for every matching parent | //item[last()] |
Zero, one, or many nodes |
| Last item in the complete document result | (//item)[last()] |
At most one node |
| Last item descendant of the current context | (.//item)[last()] |
At most one node in that scope |
| Last warning paragraph child | para[@type='warning'][last()] |
The final warning paragraph child |
Filter first, then select the last
Adjacent predicates are evaluated from left to right. This lets you define the candidate set before choosing its final position.
para[@type='warning'][last()]
Here XPath first keeps warning paragraphs, then selects the last warning paragraph. Reversing the predicates changes the meaning:
para[last()][@type='warning']
This tests only whether the last para child is a warning. If the final paragraph has another type, the result is empty—even when an earlier warning paragraph exists.
Recommended Free Tools
Other useful filter combinations
item[@status='active'][last()]selects the last active item in the relevant child sequence.(.//button[@aria-label='Next'])[last()]selects the final matching descendant button in the current scope.(//article[contains(@class, 'post')])[last()]selects the final article from the document-wide filtered result.
XPath positions are one-based
The first node has position 1, not 0. Thus item[1] selects the first item in the predicate context, while item[last()] selects the final one. To select the second-to-last item, use item[last() - 1], provided at least two matching items exist.
Numeric predicates are shorthand for position tests. item[3] means the item whose context position is three; it is equivalent to item[position() = 3].
How to use last() in browser JavaScript
Document.evaluate() evaluates XPath against a document or another node. Its second argument is the context node, so relative expressions depend on the node you provide.
const result = document.evaluate(
"(.//item)[last()]",
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
const lastItem = result.singleNodeValue;
For a body-scoped search, pass document.body and use a relative expression:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →const result = document.evaluate(
"(.//h2)[last()]",
document.body,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
const lastHeading = result.singleNodeValue;
If you expect several results, request an iterator or snapshot instead of FIRST_ORDERED_NODE_TYPE. A correct XPath can still appear to “return the wrong thing” when the host API deliberately reads only one node.
A practical method for building the XPath
- Name the scope. Decide whether the set is the current node’s children, descendants of a supplied node, or the whole document.
- Write the base selection. Start with a node test such as
item,para, or*, then add attributes or other conditions. - Choose the grouping. Keep
[last()]on a repeated child step for “last per parent”; wrap the complete path in parentheses for “last overall.” - Order predicates. Put type, class, status, or text filters before
[last()]when the last node must satisfy those conditions. - Verify the host context. Check which node the automation framework passes as the context and whether it supports the XPath functions you use.
- Inspect the cardinality. If several nodes are returned, you probably selected a last-per-parent step. If none are returned, check names, namespaces, scope, and predicate order.
Troubleshooting unexpected results
“Why does //item[last()] return several items?”
Because the predicate is evaluated for the item step under each relevant parent. Use (//item)[last()] for one final item across the complete document result, or (.//item)[last()] for one final item within the current node’s descendants.
The result is empty
- Confirm that the element name and spelling match the source tree.
- Check whether the context node is the document, a component root, or a different subtree.
- Look for XML namespaces. A prefixed XPath name must be bound to the correct namespace URI by the host API; an unprefixed name does not automatically match namespaced XML elements.
- Determine whether an earlier predicate removed every candidate before
[last()]ran.
The last element is not the one visible on screen
XPath evaluates the parsed DOM, not visual order. Client-side rendering, hidden nodes, template content, and later DOM mutations can change what exists when the expression runs. Evaluate after the page or component has finished inserting the target nodes, and scope the expression to the intended container.
A framework reports multiple matches when one was expected
Use grouped scope and an API that requests a single node, or assert the expected count before selecting. Do not silently take the first result unless “first in document order” is actually your requirement.
Compatibility is unclear
The basic last(), position(), predicates, and grouping shown here are established XPath syntax, but host products differ in XPath version, namespace APIs, and result handling. Check the implementation used by your browser, XML processor, or automation framework before relying on version-specific functions beyond this core syntax.
Testing expressions quickly
In browser developer tools, test a candidate against a known page and compare both scope and count. Start broad, then narrow:
- Evaluate
//itemto see every document-wide match. - Evaluate
//item[last()]and inspect whether one result appears per parent. - Evaluate
(//item)[last()]to verify the final node in the grouped result. - Replace
//with.//when the expression should stay inside a supplied component or container.
When debugging, temporarily remove [last()]. Seeing the full candidate list often reveals an incorrect parent, namespace, or filter long before the positional predicate is applied.
Or skip the browser setup
If your goal is to capture a page for documentation or visual inspection rather than query its DOM directly, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →One GET request returns PNG, JPEG, WebP, or PDF output:
Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for all options, including full-page lazy-image loading, CSS-selector element capture, device presets, custom viewport and retina scale, dark mode, PDF page settings, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage data, and the OpenAPI specification. Parameter names used by other screenshot APIs also work.
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
ScreenshotNeo includes an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
Frequently Asked Questions
Does [last()] mean the last element in the source file?
No. It means the item at the final position of the current predicate context. Scope and grouping determine which nodes are in that context.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsHow do I select the last child only if it has a class?
Use *[last()][contains(@class, 'name')] when the final child itself must pass the class test, or filter first with *[contains(@class, 'name')][last()] when you need the last child among all matching class elements.
Can I select the last element with CSS selectors instead?
CSS alone has no broadly supported standard selector equivalent to XPath’s document-order last(). A script can collect matching elements and index the final one, while XPath expresses the positional rule directly.
The Bottom Line
Use item[last()] for the last matching child in the current step, (//item)[last()] for the last item in a complete document result, and (.//item)[last()] for the last descendant in an explicit local scope. Apply content filters before [last()] when “last” should be calculated only among those filtered nodes.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




