When a SuiteScript automation needs a country, the difficult part is not reading one field. The difficult part is understanding whether NetSuite is returning a country name, an ISO-style code, or a record identifier. Using the wrong representation can create failed searches, incorrect integrations, and country values that appear valid but cannot be saved.
NetSuite country codes in SuiteScript are generally retrieved from a record’s country field with `getValue()` or `getText()`. Use `getValue()` when you need the stored value for comparisons or updates, and use `getText()` when you need the readable country name. Do not assume that the value is a numeric internal ID. For a complete country list, use a supported country search or SuiteQL query only after confirming the available country fields in your account’s Records Catalog.
That distinction is the central answer to how to get NetSuite country names and internal IDs with SuiteScript. A customer, vendor, address, sales order, or subsidiary record can expose country information through a select field, but the returned value depends on the API method you call. Our approach is to identify the source record, inspect the field behavior, choose the representation required by the downstream process, and test the result in the target account.
What does NetSuite return for a country field?
NetSuite country fields are select fields backed by country data, but their stored values are not always presented like ordinary numeric record IDs. In many common record contexts, the value is an ISO-style country code such as `US`, while the displayed text is a name such as `United States`.
The exact result depends on the record type, field, account configuration, and SuiteScript API method. A script should therefore treat these as different values:
| Value type | Example | Best use |
|---|---|---|
| Stored field value | `US` | Comparisons, filters, updates, integration mapping |
| Display text | `United States` | User-facing output, emails, reports |
| Record identifier | Account-specific identifier, where exposed | Direct reference to a country record or search result |
| External code | `US`, `GB`, or another partner code | Cross-system integration |
The important implementation detail is that `getValue()` and `getText()` do not answer the same question. `getValue()` returns the stored value. `getText()` returns the label NetSuite displays for the selected value. If a script needs to send a country to an external application, the stored code is usually more reliable than the display name because names can vary by language or formatting.
This is also why copying a value from the user interface and assuming it is an internal ID creates problems. NetSuite may display “United Kingdom” while the field value is `GB`. In another context, a country record search might expose a separate identifier. Those values should not be treated as interchangeable.
How do you get a NetSuite country name with SuiteScript?
Use `getText()` on the relevant country field when the script needs the readable country name. Use `getValue()` alongside it when the process also needs the stored country value.
The following SuiteScript 2.1 example reads the billing country from a loaded customer record:
/**
* @NApiVersion 2.1
*/
define(['N/record'], (record) => {
const getCustomerCountry = (customerId) => {
const customer = record.load({
type: record.Type.CUSTOMER,
id: customerId,
isDynamic: false
});
return {
value: customer.getValue({
fieldId: 'billcountry'
}),
text: customer.getText({
fieldId: 'billcountry'
})
};
};
return {
getCustomerCountry
};
});A result might resemble:
{
value: 'US',
text: 'United States'
}The actual output should be inspected in the account where the script runs. Avoid hard-coding the example result as a universal rule.
For a customer record, `billcountry` is the billing country field and `shipcountry` is commonly used for the shipping country. Other record types use different field IDs. A transaction might expose billing and shipping address fields directly, while a custom record might contain a custom select field such as `custrecord_country`.
If the script is running against the current record, `N/currentRecord` provides the same general distinction:
/**
* @NApiVersion 2.1
*/
define(['N/currentRecord'], (currentRecord) => {
const readCountry = () => {
const current = currentRecord.get();
return {
value: current.getValue({
fieldId: 'shipcountry'
}),
text: current.getText({
fieldId: 'shipcountry'
})
};
};
return {
readCountry
};
});`N/currentRecord` is appropriate for client scripts and interactive pages. It does not replace `N/record` in server-side scripts such as scheduled scripts, map/reduce scripts, or user event scripts.
How do you get a NetSuite country internal ID?
The answer depends on what “internal ID” means in the process. If the country field itself returns a stored code, that code is the value NetSuite expects for that field. It is not necessarily a numeric ID that should be converted or looked up.
For example, this comparison is appropriate when the field stores a country code:
const countryValue = customer.getValue({
fieldId: 'billcountry'
});
if (countryValue === 'US') {
// Apply United States-specific logic.
}This comparison is less reliable:
if (countryText === 'United States') {
// Avoid using display text as the primary key.
}Display text is intended for presentation. It can be affected by language, capitalization, translation, or account-specific labels. A stable stored value is generally better for business logic.
When a downstream system specifically requires a numeric country identifier, first confirm that the target field expects a country record reference rather than a country code. The Records Catalog and SuiteScript Records Browser are the right places to verify the field type and supported values. Do not convert `US` into an invented number, and do not assume the identifier is portable between accounts.
This matters in sandbox refreshes, account migrations, and multi-account deployments. NetSuite internal IDs are account-specific. A value that identifies a record in one account is not automatically the same record in another account. Our guidance on why NetSuite internal IDs should not be assumed across accounts applies to country-related lookups as well as custom records and configuration records.
How can you retrieve a full list of NetSuite countries?
For a complete list, use a country search or SuiteQL only after confirming that the country record and its fields are exposed in your account and script context. NetSuite account features and API availability affect which search types and columns are available.
A supported `N/search` country search may look like this:
/**
* @NApiVersion 2.1
*/
define(['N/search'], (search) => {
const getCountries = () => {
const countrySearch = search.create({
type: 'country',
columns: [
search.createColumn({
name: 'internalid',
sort: search.Sort.ASC
}),
search.createColumn({
name: 'name'
})
]
});
const countries = [];
countrySearch.run().each((result) => {
countries.push({
id: result.getValue({
name: 'internalid'
}),
name: result.getValue({
name: 'name'
})
});
return true;
});
return countries;
};
return {
getCountries
};
});Do not deploy this pattern without validating the search type and columns in the account. The Records Catalog provides the current schema available to your account and is more authoritative than an old code sample. If `country` is not available as a search type, the script should use the country value already present on the source record or use a maintained mapping that has been verified against the account.
A search result also introduces a separate question: does the returned `id` represent the value expected by the field you want to set? Before using it in `setValue()`, test the target field with a non-production record. A country search result identifier and a country select field value are not automatically interchangeable.
For scripts that need a country list repeatedly, caching is also important. A map/reduce or scheduled script should not run the same country lookup for every transaction when the list is stable. Load the reference data once per execution where practical, or maintain a controlled mapping in a custom record when business-specific values are required.
What is the difference between getValue() and getText()?
`getValue()` returns the field’s stored value, while `getText()` returns the field’s displayed label. That distinction applies to country fields and many other NetSuite select fields.
| SuiteScript method | Returns | Use it for |
|---|---|---|
| `getValue()` | Stored country value | Comparisons, filters, updates, integration payloads |
| `getText()` | Displayed country label | User interfaces, logs, notifications |
| `setValue()` | Writes a stored value | Setting a verified code or field value |
| `setText()` | Selects by displayed text | Controlled user-facing values, with validation |
When setting a country, prefer the method that matches the verified field behavior:
customer.setValue({
fieldId: 'billcountry',
value: 'US'
});Or, where the field supports text selection and the label is controlled:
customer.setText({
fieldId: 'billcountry',
text: 'United States'
});`setText()` is more vulnerable to label differences. If the account uses translated labels or the value has been customized, the same text may not resolve as expected. `setValue()` is generally preferable for integration and automation because it avoids matching against presentation text.
A common error occurs when a developer calls `getText()` and then passes the result into `setValue()`. The source returns `United States`, while the destination expects `US`. The script then fails validation or saves the wrong value. Keep the stored value and display text in separate variables with explicit names.
How should SuiteScript handle country values in integrations?
Integration logic should normalize country data at the boundary between NetSuite and the external system. Do not let every script, workflow, and connector invent its own country mapping.
A practical payload might preserve both representations:
const country = {
netsuiteValue: customer.getValue({
fieldId: 'shipcountry'
}),
netsuiteName: customer.getText({
fieldId: 'shipcountry'
})
};
const payload = {
countryCode: country.netsuiteValue,
countryName: country.netsuiteName
};The external application may require ISO 3166-1 alpha-2 codes, alpha-3 codes, numeric codes, or its own country key. The mapping should be explicit. If the partner expects `USA` while NetSuite returns `US`, translate that value in one controlled integration layer instead of scattering conversions across user events and client scripts.
A durable integration also records how unmatched values are handled. The script should log the source value, target system, and mapping status, then stop or route the record for review when the country is unknown. Silently sending a blank country is a data-quality problem that becomes difficult to trace later.
For larger integrations, country handling belongs in the integration architecture rather than inside a single transaction script. Our NetSuite integration platform services cover SuiteScript integrations alongside REST and SOAP-based data exchange. This is especially relevant when country values move between NetSuite, ecommerce, CRM, tax, shipping, and fulfillment systems.
Common country lookup errors in SuiteScript
The most frequent failure is assuming every country reference is a numeric internal ID. NetSuite field values must be confirmed from the actual field definition and runtime output.
Other common errors include:
Comparing `getText()` output when the business rule should use the stored code.
Calling `getValue()` on a field that is not present on the selected record type.
Using `billcountry` when the process requires `shipcountry`.
Passing a display name to `setValue()`.
Assuming a country value is portable between NetSuite accounts.
Running a search with unsupported country columns.
Building a new country mapping without documenting unknown-value behavior.
Reading sublist address data without confirming the sublist and line index.
Address sublists deserve particular attention. If the country belongs to a customer address rather than the main customer body, the script must read the address subrecord or address sublist correctly. SuiteScript sublist indexes are zero-based, and a displayed line number is not always the same as the index used by the record API. Our explanation of NetSuite line references and sublist indexes covers that distinction in detail.
A practical testing process for country fields
Country logic should be tested with more than one familiar country. Use records with different billing and shipping countries, blank values, and addresses stored in subrecords. Also test the same script role and deployment context used in production, because permissions and execution context affect what the script can read.
Before deploying, verify the following:
Identify the exact record type and field ID.
Log both `getValue()` and `getText()` in a non-production account.
Confirm whether the target field expects a code, label, or record reference.
Test blank, invalid, and unexpected country values.
Confirm integration mappings against the receiving system’s specification.
Re-test after a sandbox refresh or account migration if identifiers are involved.
Use governance carefully in batch scripts. Loading every customer record solely to read one country field is expensive. A saved search, search result, or SuiteQL query may be more efficient when the process needs many records. The right option depends on whether the script needs record behavior, display text, joins, subrecord data, or only a small set of stored values.
Conclusion
Getting NetSuite country names and internal values with SuiteScript starts with identifying what the field actually stores. Use `getValue()` for the stored country value, `getText()` for the displayed name, and never assume that a country code is a numeric internal ID. When a complete country list or external mapping is required, validate the available search schema, account for account-specific identifiers, and keep integration conversions in one controlled layer.
For help designing reliable SuiteScript lookups, country mappings, or broader NetSuite data integrations, contact Versich to discuss your requirements.

