C · recipe
Browse an OPC UA address space in C
Build a UA_BrowseRequest with a filtered UA_BrowseDescription and walk the results. Filtering in the request matters more in C than anywhere else, because every reference you fetch is memory you have to manage.
| Stack | open62541 |
|---|---|
| Version | 1.5.8 |
The code
#include <open62541/client_config_default.h>
#include <open62541/client_highlevel.h>
#include <stdio.h>
int main(void) {
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
if (UA_Client_connect(client, "opc.tcp://opcua.umati.app:4840") != UA_STATUSCODE_GOOD) {
UA_Client_delete(client); return 1;
}
UA_BrowseRequest req;
UA_BrowseRequest_init(&req);
req.requestedMaxReferencesPerNode = 100;
req.nodesToBrowse = UA_BrowseDescription_new();
req.nodesToBrowseSize = 1;
req.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
req.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_FORWARD;
req.nodesToBrowse[0].referenceTypeId =
UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES);
req.nodesToBrowse[0].includeSubtypes = true;
req.nodesToBrowse[0].nodeClassMask =
UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE;
req.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL;
UA_BrowseResponse res = UA_Client_Service_browse(client, req);
for (size_t i = 0; i < res.resultsSize; i++)
for (size_t j = 0; j < res.results[i].referencesSize; j++) {
UA_ReferenceDescription *r = &res.results[i].references[j];
printf("%d:%.*s nodeclass=%d\n",
r->browseName.namespaceIndex,
(int)r->browseName.name.length, r->browseName.name.data,
r->nodeClass);
}
UA_BrowseRequest_clear(&req);
UA_BrowseResponse_clear(&res);
UA_Client_disconnect(client);
UA_Client_delete(client);
return 0;
}
What it prints
0:Server nodeclass=1
3:Machines nodeclass=1
2:DeviceSet nodeclass=1
Notes
- Clear both the request and the response. UA_BrowseResponse_clear frees the whole reference array, and forgetting it in a loop leaks steadily until the process dies.
- requestedMaxReferencesPerNode plus continuation points is how you page a large address space. Do not ask for everything on a constrained device.
- The nodeClassMask and referenceTypeId filters cut both network traffic and the memory you have to own.
- For interactive exploration use a GUI or opcua-commander. Writing a browser in C to look around once is not a good use of anyone's afternoon.
What breaks first
A long-running browse loop grows the process's memory until it is killed
Every UA_*Response must be cleared. Run the loop under Valgrind or ASan once: open62541's own CI does exactly that.
BadOutOfMemoryEvery UA_*Response must be cleared. Run the loop under Valgrind or ASan once: open62541's own CI does exactly that.
Other recipes in this stack
Concepts on this page
Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.