This module offers classes representing filesystem paths with semantics
appropriate for different operating systems. Path classes are divided
between pure paths, which provide purely computational
operations without I/O, and concrete paths, which
inherit from pure paths but also provide I/O operations.
If you’ve never used this module before or just aren’t sure which class is
right for your task, Path is most likely what you need. It instantiates
a concrete path for the platform the code is running on.
Pure paths are useful in some special cases; for example:
If you want to manipulate Windows paths on a Unix machine (or vice versa).
You cannot instantiate a WindowsPath when running on Unix, but you
can instantiate PureWindowsPath.
You want to make sure that your code only manipulates paths without actually
accessing the OS. In this case, instantiating one of the pure classes may be
useful since those simply don’t have any OS-accessing operations.
See also
PEP 428: The pathlib module – object-oriented filesystem paths.
See also
For low-level path manipulation on strings, you can also use the
os.path module.
Pure path objects provide path-handling operations which don’t actually
access a filesystem. There are three ways to access these classes, which
we also call flavours:
A generic class that represents the system’s path flavour (instantiating
it creates either a PurePosixPath or a PureWindowsPath):
>>> PurePath('setup.py')# Running on a Unix machinePurePosixPath('setup.py')
Each element of pathsegments can be either a string representing a
path segment, or an object implementing the os.PathLike interface
where the __fspath__() method returns a string,
such as another path object:
Spurious slashes and single dots are collapsed, but double dots ('..')
and leading double slashes ('//') are not, since this would change the
meaning of a path for various reasons (e.g. symbolic links, UNC paths):
(a naïve approach would make PurePosixPath('foo/../bar') equivalent
to PurePosixPath('bar'), which is wrong if foo is a symbolic link
to another directory)
Pure path objects implement the os.PathLike interface, allowing them
to be used anywhere the interface is accepted.
Changed in version 3.6: Added support for the os.PathLike interface.
Paths of a different flavour compare unequal and cannot be ordered:
>>> PureWindowsPath('foo')==PurePosixPath('foo')False>>> PureWindowsPath('foo')<PurePosixPath('foo')Traceback (most recent call last):
File "<stdin>", line 1, in <module>TypeError: '<' not supported between instances of 'PureWindowsPath' and 'PurePosixPath'
The slash operator helps create child paths, like os.path.join().
If the argument is an absolute path, the previous path is ignored.
On Windows, the drive is not reset when the argument is a rooted
relative path (e.g., r'\foo'):
The string representation of a path is the raw filesystem path itself
(in native form, e.g. with backslashes under Windows), which you can
pass to any function taking a file path as a string:
This behavior conforms to The Open Group Base Specifications Issue 6,
paragraph 4.11 Pathname Resolution:
“A pathname that begins with two successive slashes may be interpreted in
an implementation-defined manner, although more than two leading slashes
shall be treated as a single slash.”
If you want to walk an arbitrary filesystem path upwards, it is
recommended to first call Path.resolve() so as to resolve
symlinks and eliminate ".." components.
Patterns ending in “/**”, as in the example above, may surprise when
passed to full_match. Even though “**” can match 0 segments,
“.../**” requires a separator to match. Hence “/a/**” does not
match path “/a”. Since PurePath drops trailing slashes, this
pattern also does not match “/a/”.
Match this path against the provided non-recursive glob-style pattern.
Return True if matching is successful, False otherwise.
This method is similar to full_match(), but empty patterns
aren’t allowed (ValueError is raised), the recursive wildcard
“**” isn’t supported (it acts like non-recursive “*”), and if a
relative pattern is provided, then matching is done from the right:
Compute a version of this path relative to the path represented by
other. If it’s impossible, ValueError is raised:
>>> p=PurePosixPath('/etc/passwd')>>> p.relative_to('/')PurePosixPath('etc/passwd')>>> p.relative_to('/etc')PurePosixPath('passwd')>>> p.relative_to('/usr')Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pathlib.py", line 941, in relative_toraiseValueError(error_message.format(str(self),str(formatted)))ValueError: '/etc/passwd' is not in the subpath of '/usr' OR one path is relative and the other is absolute.
When walk_up is false (the default), the path must start with other.
When the argument is true, .. entries may be added to form the
relative path. In all other cases, such as the paths referencing
different drives, ValueError is raised.:
>>> p.relative_to('/usr',walk_up=True)PurePosixPath('../etc/passwd')>>> p.relative_to('foo',walk_up=True)Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pathlib.py", line 941, in relative_toraiseValueError(error_message.format(str(self),str(formatted)))ValueError: '/etc/passwd' is not on the same drive as 'foo' OR one path is relative and the other is absolute.
Warning
This function is part of PurePath and works with strings.
It does not check or access the underlying file structure.
This can impact the walk_up option as it assumes that no symlinks
are present in the path; call resolve() first if
necessary to resolve symlinks.
Changed in version 3.12: The walk_up parameter was added (old behavior is the same as walk_up=False).
Deprecated since version 3.12, removed in version 3.14: Passing additional positional arguments is deprecated; if supplied,
they are joined with other.
Return a new path with the name changed. If the original path
doesn’t have a name, ValueError is raised:
>>> p=PureWindowsPath('c:/Downloads/pathlib.tar.gz')>>> p.with_name('setup.py')PureWindowsPath('c:/Downloads/setup.py')>>> p=PureWindowsPath('c:/')>>> p.with_name('setup.py')Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/antoine/cpython/default/Lib/pathlib.py", line 751, in with_nameraiseValueError("%r has an empty name"%(self,))ValueError: PureWindowsPath('c:/') has an empty name
Return a new path with the stem changed. If the original path
doesn’t have a name, ValueError is raised:
>>> p=PureWindowsPath('c:/Downloads/draft.txt')>>> p.with_stem('final')PureWindowsPath('c:/Downloads/final.txt')>>> p=PureWindowsPath('c:/Downloads/pathlib.tar.gz')>>> p.with_stem('lib')PureWindowsPath('c:/Downloads/lib.gz')>>> p=PureWindowsPath('c:/')>>> p.with_stem('')Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/antoine/cpython/default/Lib/pathlib.py", line 861, in with_stemreturnself.with_name(stem+self.suffix)
File "/home/antoine/cpython/default/Lib/pathlib.py", line 851, in with_nameraiseValueError("%r has an empty name"%(self,))ValueError: PureWindowsPath('c:/') has an empty name
Return a new path with the suffix changed. If the original path
doesn’t have a suffix, the new suffix is appended instead. If the
suffix is an empty string, the original suffix is removed:
Create a new path object of the same type by combining the given
pathsegments. This method is called whenever a derivative path is created,
such as from parent and relative_to(). Subclasses may
override this method to pass information to derivative paths, for example:
Concrete paths are subclasses of the pure path classes. In addition to
operations provided by the latter, they also provide methods to do system
calls on path objects. There are three ways to instantiate concrete paths:
A subclass of PurePath, this class represents concrete paths of
the system’s path flavour (instantiating it creates either a
PosixPath or a WindowsPath):
You can only instantiate the class flavour that corresponds to your system
(allowing system calls on non-compatible path flavours could lead to
bugs or failures in your application):
>>> importos>>> os.name'posix'>>> Path('setup.py')PosixPath('setup.py')>>> PosixPath('setup.py')PosixPath('setup.py')>>> WindowsPath('setup.py')Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pathlib.py", line 798, in __new__%(cls.__name__,))UnsupportedOperation: cannot instantiate 'WindowsPath' on your system
Some concrete path methods can raise an OSError if a system call fails
(for example because the path doesn’t exist).
ValueError is raised if the URI does not start with file:, or
the parsed path isn’t absolute.
Added in version 3.13.
Changed in version 3.14: The URL authority is discarded if it matches the local hostname.
Otherwise, if the authority isn’t empty or localhost, then on
Windows a UNC path is returned (as before), and on other platforms a
ValueError is raised.
Deprecated since version 3.14, will be removed in version 3.19: Calling this method from PurePath rather than Path is
possible but deprecated. The method’s use of os.fsencode() makes
it strictly impure.
Return a new path object representing the user’s home directory (as
returned by os.path.expanduser() with ~ construct). If the home
directory can’t be resolved, RuntimeError is raised.
Return a new path with expanded ~ and ~user constructs,
as returned by os.path.expanduser(). If a home directory can’t be
resolved, RuntimeError is raised.
If a path doesn’t exist or a symlink loop is encountered, and strict is
True, OSError is raised. If strict is False, the path is
resolved as far as possible and any remainder is appended without checking
whether it exists.
Changed in version 3.6: The strict parameter was added (pre-3.6 behavior is strict).
Changed in version 3.13: Symlink loops are treated like other errors: OSError is raised in
strict mode, and no exception is raised in non-strict mode. In previous
versions, RuntimeError is raised no matter the value of strict.
Changed in version 3.14: The methods given above now return False instead of raising any
OSError exception from the operating system. In previous versions,
some kinds of OSError exception are raised, and others suppressed.
The new behaviour is consistent with os.path.exists(),
os.path.isdir(), etc. Use stat() to retrieve the file
status without suppressing exceptions.
Return True if the path points to an existing file or directory and
False if the path is invalid, inaccessible or missing.
Use Path.stat() to distinguish between these cases.
This method normally follows symlinks; to check if a symlink exists, add
the argument follow_symlinks=False.
>>> Path('').exists()# The current directory.True>>> Path('.').exists()True>>> Path('setup.py').exists()True>>> Path('/etc').exists()True>>> Path('nonexistentfile').exists()False
Changed in version 3.12: The follow_symlinks parameter was added.
Return True if the path points to a regular file. False will be
returned if the path is invalid, inaccessible or missing, or if it points
to something other than a regular file. Use Path.stat() to
distinguish between these cases.
This method normally follows symlinks; to exclude symlinks, add the
argument follow_symlinks=False.
Changed in version 3.13: The follow_symlinks parameter was added.
Return True if the path points to a directory. False will be
returned if the path is invalid, inaccessible or missing, or if it points
to something other than a directory. Use Path.stat() to distinguish
between these cases.
This method normally follows symlinks; to exclude symlinks to directories,
add the argument follow_symlinks=False.
Changed in version 3.13: The follow_symlinks parameter was added.
Return True if the path points to a symbolic link, even if that symlink
is broken. False will be returned if the path is invalid, inaccessible
or missing, or if it points to something other than a symbolic link. Use
Path.stat() to distinguish between these cases.
Return True if the path is a mount point: a point in a
file system where a different file system has been mounted. On POSIX, the
function checks whether path’s parent, path/.., is on a different
device than path, or whether path/.. and path point to the same
i-node on the same device — this should detect mount points for all Unix
and POSIX variants. On Windows, a mount point is considered to be a drive
letter root (e.g. c:\), a UNC share (e.g. \\server\share), or a
mounted filesystem directory.
Added in version 3.7.
Changed in version 3.12: Windows support was added.
Return True if the path points to a Unix socket. False will be
returned if the path is invalid, inaccessible or missing, or if it points
to something other than a Unix socket. Use Path.stat() to
distinguish between these cases.
Return True if the path points to a FIFO. False will be returned if
the path is invalid, inaccessible or missing, or if it points to something
other than a FIFO. Use Path.stat() to distinguish between these
cases.
Return True if the path points to a block device. False will be
returned if the path is invalid, inaccessible or missing, or if it points
to something other than a block device. Use Path.stat() to
distinguish between these cases.
Return True if the path points to a character device. False will be
returned if the path is invalid, inaccessible or missing, or if it points
to something other than a character device. Use Path.stat() to
distinguish between these cases.
Return whether this path points to the same file as other_path, which
can be either a Path object, or a string. The semantics are similar
to os.path.samefile() and os.path.samestat().
An OSError can be raised if either file cannot be accessed for some
reason.
A PathInfo object that supports querying file type
information. The object exposes methods that cache their results, which can
help reduce the number of system calls needed when switching on file type.
For example:
If the path was generated from Path.iterdir() then this attribute is
initialized with some information about the file type gleaned from scanning
the parent directory. Merely accessing Path.info does not perform
any filesystem queries.
To fetch up-to-date information, it’s best to call Path.is_dir(),
is_file() and is_symlink() rather than methods of
this attribute. There is no way to reset the cache; instead you can create
a new path object with an empty info cache via p=Path(p).
The children are yielded in arbitrary order, and the special entries
'.' and '..' are not included. If a file is removed from or added
to the directory after creating the iterator, it is unspecified whether
a path object for that file is included.
If the path is not a directory or otherwise inaccessible, OSError is
raised.
By default, or when the case_sensitive keyword-only argument is set to
None, this method matches paths using platform-specific casing rules:
typically, case-sensitive on POSIX, and case-insensitive on Windows.
Set case_sensitive to True or False to override this behaviour.
By default, or when the recurse_symlinks keyword-only argument is set to
False, this method follows symlinks except when expanding “**”
wildcards. Set recurse_symlinks to True to always follow symlinks.
Note
Any OSError exceptions raised from scanning the filesystem are
suppressed. This includes PermissionError when accessing
directories without read permission.
Raises an auditing eventpathlib.Path.glob with arguments self, pattern.
Changed in version 3.12: The case_sensitive parameter was added.
Changed in version 3.13: The recurse_symlinks parameter was added.
Changed in version 3.13: The pattern parameter accepts a path-like object.
Changed in version 3.13: Any OSError exceptions raised from scanning the filesystem are
suppressed. In previous versions, such exceptions are suppressed in many
cases, but not all.
Glob the given relative pattern recursively. This is like calling
Path.glob() with “**/” added in front of the pattern.
Note
The paths are returned in no particular order.
If you need a specific order, sort the results.
Note
Any OSError exceptions raised from scanning the filesystem are
suppressed. This includes PermissionError when accessing
directories without read permission.
Generate the file names in a directory tree by walking the tree
either top-down or bottom-up.
For each directory in the directory tree rooted at self (including
self but excluding ‘.’ and ‘..’), the method yields a 3-tuple of
(dirpath,dirnames,filenames).
dirpath is a Path to the directory currently being walked,
dirnames is a list of strings for the names of subdirectories in dirpath
(excluding '.' and '..'), and filenames is a list of strings for
the names of the non-directory files in dirpath. To get a full path
(which begins with self) to a file or directory in dirpath, do
dirpath/name. Whether or not the lists are sorted is file
system-dependent.
If the optional argument top_down is true (which is the default), the triple for a
directory is generated before the triples for any of its subdirectories
(directories are walked top-down). If top_down is false, the triple
for a directory is generated after the triples for all of its subdirectories
(directories are walked bottom-up). No matter the value of top_down, the
list of subdirectories is retrieved before the triples for the directory and
its subdirectories are walked.
When top_down is true, the caller can modify the dirnames list in-place
(for example, using del or slice assignment), and Path.walk()
will only recurse into the subdirectories whose names remain in dirnames.
This can be used to prune the search, or to impose a specific order of visiting,
or even to inform Path.walk() about directories the caller creates or
renames before it resumes Path.walk() again. Modifying dirnames when
top_down is false has no effect on the behavior of Path.walk() since the
directories in dirnames have already been generated by the time dirnames
is yielded to the caller.
By default, errors from os.scandir() are ignored. If the optional
argument on_error is specified, it should be a callable; it will be
called with one argument, an OSError instance. The callable can handle the
error to continue the walk or re-raise it to stop the walk. Note that the
filename is available as the filename attribute of the exception object.
By default, Path.walk() does not follow symbolic links, and instead adds them
to the filenames list. Set follow_symlinks to true to resolve symlinks
and place them in dirnames and filenames as appropriate for their targets, and
consequently visit directories pointed to by symlinks (where supported).
Note
Be aware that setting follow_symlinks to true can lead to infinite
recursion if a link points to a parent directory of itself. Path.walk()
does not keep track of the directories it has already visited.
Note
Path.walk() assumes the directories it walks are not modified during
execution. For example, if a directory from dirnames has been replaced
with a symlink and follow_symlinks is false, Path.walk() will
still try to descend into it. To prevent such behavior, remove directories
from dirnames as appropriate.
Note
Unlike os.walk(), Path.walk() lists symlinks to directories in
filenames if follow_symlinks is false.
This example displays the number of bytes used by all files in each directory,
while ignoring __pycache__ directories:
This next example is a simple implementation of shutil.rmtree().
Walking the tree bottom-up is essential as rmdir() doesn’t allow
deleting a directory before it is empty:
# Delete everything reachable from the directory "top".# CAUTION: This is dangerous! For example, if top == Path('/'),# it could delete all of your files.forroot,dirs,filesintop.walk(top_down=False):fornameinfiles:(root/name).unlink()fornameindirs:(root/name).rmdir()
Create a file at this given path. If mode is given, it is combined
with the process’s umask value to determine the file mode and access
flags. If the file already exists, the function succeeds when exist_ok
is true (and its modification time is updated to the current time),
otherwise FileExistsError is raised.
Create a new directory at this given path. If mode is given, it is
combined with the process’s umask value to determine the file mode
and access flags. If the path already exists, FileExistsError
is raised.
If parents is true, any missing parents of this path are created
as needed; they are created with the default permissions without taking
mode into account (mimicking the POSIX mkdir-p command).
If parent_mode is not None, it is used as the mode for any
newly-created, intermediate-level directories when parents is true.
Like mode, it is combined with the process’s umask value.
Otherwise, intermediate directories are created with the default
permissions (also subject to the umask).
If parents is false (the default), a missing parent raises
FileNotFoundError.
If exist_ok is false (the default), FileExistsError is
raised if the target directory already exists.
If exist_ok is true, FileExistsError will not be raised unless the given
path already exists in the file system and is not a directory (same
behavior as the POSIX mkdir-p command).
Changed in version 3.5: The exist_ok parameter was added.
Make this path a symbolic link pointing to target.
On Windows, a symlink represents either a file or a directory, and does not
morph to the target dynamically. If the target is present, the type of the
symlink will be created to match. Otherwise, the symlink will be created
as a directory if target_is_directory is true or a file symlink (the
default) otherwise. On non-Windows platforms, target_is_directory is ignored.
Copy this file or directory tree to the given target, and return a new
Path instance pointing to target.
If the source is a file, the target will be replaced if it is an existing
file. If the source is a symlink and follow_symlinks is true (the
default), the symlink’s target is copied. Otherwise, the symlink is
recreated at the destination.
If preserve_metadata is false (the default), only directory structures
and file data are guaranteed to be copied. Set preserve_metadata to true
to ensure that file and directory permissions, flags, last access and
modification times, and extended attributes are copied where supported.
This argument has no effect when copying files on Windows (where
metadata is always preserved).
Note
Where supported by the operating system and file system, this method
performs a lightweight copy, where data blocks are only copied when
modified. This is known as copy-on-write.
Copy this file or directory tree into the given target_dir, which should
be an existing directory. Other arguments are handled identically to
Path.copy(). Returns a new Path instance pointing to the
copy.
Rename this file or directory to the given target, and return a new
Path instance pointing to target. On Unix, if target exists
and is a file, it will be replaced silently if the user has permission.
On Windows, if target exists, FileExistsError will be raised.
target can be either a string or another path object:
The target path may be absolute or relative. Relative paths are interpreted
relative to the current working directory, not the directory of the
Path object.
It is implemented in terms of os.rename() and gives the same guarantees.
Changed in version 3.8: Added return value, return the new Path instance.
Rename this file or directory to the given target, and return a new
Path instance pointing to target. If target points to an
existing file or empty directory, it will be unconditionally replaced.
The target path may be absolute or relative. Relative paths are interpreted
relative to the current working directory, not the directory of the
Path object.
Changed in version 3.8: Added return value, return the new Path instance.
Move this file or directory tree to the given target, and return a new
Path instance pointing to target.
If the target doesn’t exist it will be created. If both this path and the
target are existing files, then the target is overwritten. If both paths
point to the same file or directory, or the target is a non-empty
directory, then OSError is raised.
If both paths are on the same filesystem, the move is performed with
os.replace(). Otherwise, this path is copied (preserving metadata and
symlinks) and then deleted.
Move this file or directory tree into the given target_dir, which should
be an existing directory. Returns a new Path instance pointing to
the moved path.
Change the file mode and permissions, like os.chmod().
This method normally follows symlinks. Some Unix flavours support changing
permissions on the symlink itself; on these platforms you may add the
argument follow_symlinks=False, or use lchmod().
Matches any number of file or directory segments, including zero.
Note that in full_match(), “a/**” does not match
“a”, whereas glob() yields “a” for that pattern.
* (entire segment)
Matches one file or directory segment.
* (part of a segment)
Matches any number of non-separator characters, including zero.
?
Matches one non-separator character.
[seq]
Matches one character in seq, where seq is a sequence of characters.
Range expressions are supported; for example, [a-z] matches any lowercase ASCII letter.
Multiple ranges can be combined: [a-zA-Z0-9_] matches any ASCII letter, digit, or underscore.
[!seq]
Matches one character not in seq, where seq follows the same rules as above.
For a literal match, wrap the meta-characters in brackets.
For example, "[?]" matches the character "?".
The “**” wildcard enables recursive globbing. A few examples:
Pattern
Meaning
“**/*”
Any path with at least one segment.
“**/*.py”
Any path with a final segment ending “.py”.
“assets/**”
Any path starting with “assets/”.
“assets/**/*”
Any path starting with “assets/”, excluding “assets/” itself.
Note
Globbing with the “**” wildcard visits every directory in the tree.
Large directory trees may take a long time to search.
Changed in version 3.13: Globbing with a pattern that ends with “**” returns both files and
directories. In previous versions, only directories were returned.
In Path.glob() and rglob(), a trailing slash may be added to
the pattern to match only directories.
Changed in version 3.11: Globbing with a pattern that ends with a pathname components separator
(sep or altsep) returns only directories.
The patterns accepted and results generated by Path.glob() and
Path.rglob() differ slightly from those by the glob module:
Files beginning with a dot are not special in pathlib. This is
like passing include_hidden=True to glob.glob().
“**” pattern components are always recursive in pathlib. This is like
passing recursive=True to glob.glob().
“**” pattern components do not follow symlinks by default in pathlib.
This behaviour has no equivalent in glob.glob(), but you can pass
recurse_symlinks=True to Path.glob() for compatible behaviour.
The values returned from pathlib’s path.glob() and path.rglob()
include the path as a prefix, unlike the results of
glob.glob(root_dir=path).
The values returned from pathlib’s path.glob() and path.rglob()
may include path itself, for example when globbing “**”, whereas the
results of glob.glob(root_dir=path) never include an empty string that
would correspond to path.
pathlib implements path operations using PurePath and Path
objects, and so it’s said to be object-oriented. On the other hand, the
os and os.path modules supply functions that work with low-level
str and bytes objects, which is a more procedural approach. Some
users consider the object-oriented style to be more readable.
Python’s str and bytes types, and portions of the os and
os.path modules, are written in C and are very speedy. pathlib is
written in pure Python and is often slower, but rarely slow enough to matter.
pathlib’s path normalization is slightly more opinionated and consistent than
os.path. For example, whereas os.path.abspath() eliminates
“..” segments from a path, which may change its meaning if symlinks are
involved, Path.absolute() preserves these segments for greater safety.
pathlib’s path normalization may render it unsuitable for some applications:
pathlib normalizes Path("my_folder/") to Path("my_folder"), which
changes a path’s meaning when supplied to various operating system APIs and
command-line utilities. Specifically, the absence of a trailing separator
may allow the path to be resolved as either a file or directory, rather
than a directory only.
pathlib normalizes Path("./my_program") to Path("my_program"),
which changes a path’s meaning when used as an executable search path, such
as in a shell or when spawning a child process. Specifically, the absence
of a separator in the path may force it to be looked up in PATH
rather than the current directory.
As a consequence of these differences, pathlib is not a drop-in replacement
for os.path.
Return True if the path is a directory, or a symbolic link pointing
to a directory; return False if the path is (or points to) any other
kind of file, or if it doesn’t exist.
If follow_symlinks is False, return True only if the path
is a directory (without following symlinks); return False if the
path is any other kind of file, or if it doesn’t exist.
Return True if the path is a file, or a symbolic link pointing to
a file; return False if the path is (or points to) a directory or
other non-file, or if it doesn’t exist.
If follow_symlinks is False, return True only if the path
is a file (without following symlinks); return False if the path
is a directory or other non-file, or if it doesn’t exist.
The Python Software Foundation is a non-profit corporation.
Please donate.
Last updated on Nov 12, 2026 (21:32 UTC).
Found a bug?
Created using Sphinx 9.1.1.
You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.